Type name as string

S

Severin Ecker

Hi,

I'm not aware of any solution but hopefully there is a way that I just
don't know.
Can I get the name of a type as string (literal) in a consistent
platform independent way?
Since I only need this information statically I could use (and prefer) a
compile time possibility (i.e.: I won't need to query the type name of
an object at runtime), basically it's something like:

template <class T>
struct TypeName
{
static const char* name = //somehow get the name of T;
};

so

TypeName<int>::name == "int";

and
struct bla {};
TypeName<bla>::name == "bla";


I know that the type_info::name is implementation dependent so that's
not an option (additionally it doesn't even have to be related to the
name you type in the code as far as I'm aware of as long as it's
unambiguous) but since the compiler has all the knowledge that I need I
was hoping that there's a way to get the info from it.

In essence what I'm trying/needing to do (and before you ask, yes I do
need the thing as string and can't just let the type system figure it
out for me) is the following (and I really would like to save the
tedious work of dozens of specializations for all the types that can
actually be used for Foo):

template <class T> std::string GetCast(T t) { return ""; };

template <class T> std::string GetCast(T* t)
{
std::string cast("(");
cast += std::string(TypeName<T>::name) + ")";
return cast;
}


my thanks in advance.
cheers,
severin
 
A

Alf P. Steinbach

* Severin Ecker:
Hi,

I'm not aware of any solution but hopefully there is a way that I just
don't know.
Can I get the name of a type as string (literal) in a consistent
platform independent way?

Yes, but as of C++98 you have to implement that yourself -- typeid is
platform-specific.

Since I only need this information statically I could use (and prefer) a
compile time possibility (i.e.: I won't need to query the type name of
an object at runtime), basically it's something like:

template <class T>
struct TypeName
{
static const char* name = //somehow get the name of T;
};

so

TypeName<int>::name == "int";

and
struct bla {};
TypeName<bla>::name == "bla";


I know that the type_info::name is implementation dependent so that's
not an option (additionally it doesn't even have to be related to the
name you type in the code as far as I'm aware of as long as it's
unambiguous) but since the compiler has all the knowledge that I need I
was hoping that there's a way to get the info from it.

In essence what I'm trying/needing to do (and before you ask, yes I do
need the thing as string and can't just let the type system figure it
out for me) is the following (and I really would like to save the
tedious work of dozens of specializations for all the types that can
actually be used for Foo):

template <class T> std::string GetCast(T t) { return ""; };

template <class T> std::string GetCast(T* t)
{
std::string cast("(");
cast += std::string(TypeName<T>::name) + ")";
return cast;
}

Ugh, *generating* bad C code.

Oh well.

Since that's already very dirty, consider using compiler-specific means, and in
the worst case accessing the generated debug information. There is an
introspection library for gcc that may help (for that compiler). But why on
Earth do you want to generate bad C-code based on your C++ program's internals?

Just in case the above example is misleading, I should also mention the
preprocessor's stringizing operator.

The stringizing operator may help you if you know the concrete type name in the
calling code, but not if above example is invoked from code templated on T.


Cheers & hth.,

- Alf
 
P

Pascal J. Bourguignon

Severin Ecker said:
Hi,

I'm not aware of any solution but hopefully there is a way that I just
don't know.
Can I get the name of a type as string (literal) in a consistent
platform independent way?

No. At least not without a lot of work on your part.

Since I only need this information statically I could use (and prefer)
a compile time possibility


Well you could use a macro:

------------------------------------------------------------------------
#include <iostream>
#define TYPENAME(TYPE) #TYPE
int main(){
std::string typeOfFun=TYPENAME( int(*)(float,char*) );
int(*fun)(float,char*);
std::cout<<"fun is of type "<<typeOfFun<<std::endl;
return(0);
}
/*
-*- mode: compilation; default-directory: "/tmp/" -*-
Compilation started at Fri Mar 13 10:35:44

SRC="/tmp/t.c++" ; EXE="t" ; g++ -I$HOME/opt/libanevia-1.0.0-manager2-trunk-debug/include/libanevia-1.0/ -L$HOME/opt/libanevia-1.0.0-manager2-trunk-debug/lib/ -lanevia -g3 -ggdb3 -o ${EXE} ${SRC} && ./${EXE} && echo status = $?
fun is of type int(*)(float,char*)
status = 0

Compilation finished at Fri Mar 13 10:35:46
*/
------------------------------------------------------------------------


(i.e.: I won't need to query the type name
of an object at runtime), basically it's something like:

template <class T>
struct TypeName
{
static const char* name = //somehow get the name of T;
};

The above macro wouldn't work in this situation, because the cpp
macros are expanded before templates are processed.
TypeName<int>::name == "int";

Writting such a macro would be a lot of work.
Perhaps you could study the code of the boost library, to see what would be involved.




If you're really keen on this feature, perhaps I may suggest you to switch from C++ to CL?

In CL (Common Lisp), it's trivial:

(defvar *example* (case (random 3)
(0 42)
(1 "fourty-two")
(2 #(4 2))))
(defvar *name-of-type-of-example* (princ-to-string (type-of *example*)))

*name-of-type-of-example*
--> (INTEGER 0 281474976710655)" ; for example, a value of another type could have been instanciated instead.
 
S

SG

In essence what I'm trying/needing to do [...] is the following

template <class T> std::string GetCast(T t) { return ""; };

template <class T> std::string GetCast(T* t)
{
    std::string cast("(");
    cast += std::string(TypeName<T>::name) + ")";
    return cast;
}

What do you need this for?
(translation: What are you *really* trying to do?)

I'm asking because it seems likely to me that you don't need something
like this.

Cheers!
SG
 
S

Severin Ecker

Hi,
* Severin Ecker:

Yes, but as of C++98 you have to implement that yourself -- typeid is
platform-specific.



Ugh, *generating* bad C code.

Oh well.

Since that's already very dirty, consider using compiler-specific means,
and in the worst case accessing the generated debug information. There
is an introspection library for gcc that may help (for that compiler).
But why on Earth do you want to generate bad C-code based on your C++
program's internals?

Since you're asking. Because the scripting interpreter library that I'm
using needs a string to invoke a function. This interpreter can only
work with 'evaluated' parameters.

assume the following functions within the 'script':
void func(int d) { d = 3; }
void ptrfunc(int* p) { *p = 3; }


e.g.:

int i = 5;
runfunc("func(i)");

won't work because within the interpreter environment 'i' is unknown but

runfunc("func(5)");

does work however


apart from fundamental types the scripting interpreter can work on
pointers but there's the catch:
again:

runfunc("ptrfunc(&i)");

won't work because again 'i' is unknown within the interpreter
environment. so what do we do? right just pass the address:

runfunc("ptrfunc(0x123)"); // assuming that 0x123 is the address if i

now this again does not work because the interpreter sees 0x123 and
assumes it to be an int (it just doesn't care that the function actually
expects a pointer. so in essence internally it creates an int variable
whose value is 0x123 and passes the address of _that variable_ to
ptrfunc since yes, ptrfunc expects a pointer) BANG we will write some
memory we never intended to.

so how do we convince the interpreter to do what we want? exactly cast
the address to a pointer like:

runfunc("ptrfunc((void*)0x123)");

this works like a charm. the actual type of the casting expression
doesn't matter at all, it just flags the value as being an address not
an integer value and without going into more internal details it just
works and after the function has run, our i holds the value 3.

of course there's some code around this 'raw' function call so that the
user can more conveniently (more or less) just write (so RUN is a macro
which passes the 2nd parameter to the template function which either
converts the value of T into a string, or the address to a cast
expression if it's a pointer and then wraps it up in a
'string-function-call' that's needed by the interpreter.)

RUN(ptrfunc, &i);

which will convert it to the above mentioned string.

BUT. the user can also do the following

struct foo { ... };

foo f;

RUN(ptrfunc, &f);

which will run without complaint but as you can see &f will then be used
as pointer to int rather than pointer to f.

Now if i can get an invocation like

runfunc("ptrfunc((int*)0x123)");

or

runfunc("ptrfunc((foo*)0x456)");

instead of the void, i to have a change to check the expected type of
the script function and the passed type, which would just minimize
mistakes. Of course intentional breaking the think works just fine, but
that's not the issue at hand.

hope this answers some open questions.
Just in case the above example is misleading, I should also mention the
preprocessor's stringizing operator.

The stringizing operator may help you if you know the concrete type name
in the calling code, but not if above example is invoked from code
templated on T.

well yes, indeed this is the case unfortunately.

cheers,
severin
 
S

Severin Ecker

SG said:
In essence what I'm trying/needing to do [...] is the following

template <class T> std::string GetCast(T t) { return ""; };

template <class T> std::string GetCast(T* t)
{
std::string cast("(");
cast += std::string(TypeName<T>::name) + ")";
return cast;
}

What do you need this for?
(translation: What are you *really* trying to do?)

I'm asking because it seems likely to me that you don't need something
like this.

please check my reply to Alf's post, i hope this answers your question.

cheers,
severin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top