Getting template parameter as string

Eaa9847123e828897f960de0badf1ffa
0
Alex 101 Mar 15, 2007 at 15:04

Hi guys,

I’m having a little trouble …
Basically what I’d like to do is that a class template should return one of its parameters as a string like this:

#define ToStr(val) #val

template <class T>
cTest
{

    T* mT;
    //..some stuff using mT

    char* GetName()
    {
        return ToStr(T);
    }

};

This compiles but GetName() returns “T”, not the actual parameter.
I tried to pass the parameter name as another template parameter:

template <class T,char* NAME=ToStr(T)>
...

This doesn’t compile because:
“invalid expression as a template argument for NAME”.
It won’t compile for anything I tried but a NULL ptr.

SO what’s the way to do this??

Thx,
ALex

7 Replies

Please log in or register to post a reply.

A9102969e779768e6f0b8cb87e864c94
0
dave_ 101 Mar 15, 2007 at 19:23

I’m afraid you can’t do that.
You can however use typeid(T).name() provided you haven’t disabled RTTI.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Mar 15, 2007 at 20:58

To expand on dave’s answer…

The first way doesn’t work because the preprocessor (which is what handles #defines) works before the actual compiler even starts. So ToStr(T) gets substituted with “T” regardless of T’s status as a template parameter or anything else.

The second way doesn’t work because template parameters are only allowed to be typenames and enumerable types (basically, ints). This is because the compiler generates a new copy of the template for each combination of parameters. If things like pointers or floats were allowed, it would be extremely easy to accidentally create an enormous number of copies of the template.

Eaa9847123e828897f960de0badf1ffa
0
Alex 101 Mar 15, 2007 at 21:14

The docu says that pointers are actually allowed as template arg. It seams an array cannot be defined so that it is accepted as a template arg.
(At least in visual studio 8)

I’d rather not use rtti.

Thx for the answers..
I kinda found a way around it. I define a “template” class using a macro. Inside that I can just use T the way I like..and the way I think it should be :)

Alex

A9102969e779768e6f0b8cb87e864c94
0
dave_ 101 Mar 16, 2007 at 00:19

Just out of curiosity, why wont you use RTTI?

In the old days it used to have a big impact on code size, but now on MSVC and GCC are both pretty good with it.

In the past without RTTI I’ve used something like this:

template <class T>
cTest
{
    char* GetName()
    {
        return T::GetName();
    }

};

And for all classes that we want to use implement

class MyClass
{
    static const char* GetName() { return "MyClass"; }
    // .. lots more code
};

for every class that used the templated function.

It really wasn’t that many classes.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Mar 16, 2007 at 00:36

You can use the typeid thingy in VS without the need of enabling RTTI, as the types are statically typed. You’ll need RTTI for dynamic_casts and typeid’s of pointers/references to polymorphic types.

As for the template arguments, pointers and references are allowed but only for named objects with external linkage. A string literal is not such an object. This, however, does work:

template<const char *> struct S { };
const char MyString[] = "Hello World";
S<MyString> s;

Of course, that doesn’t solve your problem as preprocessing is completely independent of the actual semantics of the language :blink:

Also, there are thoughts in the committee to allow floats as template arguments if I’m not mistaken :)

Eaa9847123e828897f960de0badf1ffa
0
Alex 101 Mar 16, 2007 at 14:13

@.oisin

I tried that..using your code I get:

.\TestMain.cpp(1219) : error C2970: ‘S’ : template parameter ‘unnamed-parameter’ : ‘MyString’ : an expression involving objects with internal linkage cannot be used as a non-type argument
.\TestMain.cpp(1217) : see declaration of ‘S’
.\TestMain.cpp(1218) : see declaration of ‘MyString’

I haven’t found a way to declare an array so that it is accepted as template argument.

@_dave

I wanted to avoid adding the GetName() function to each class as these are very generic classes used as events and as interface handler. So I have tons of instances that would require adding the function.

As for rtti,..well I kinda dislike enabling it for this single small thingy..I don’t need it anywhere else.

typeid(T).name() appears to be doing what I need…cool

Alex

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Mar 16, 2007 at 16:13

Oh my bad, MyString isn’t seen as being external if it’s just const. It works if you drop the ‘const’ of MyString -or- if you define it as being external:

template<const char *> struct S { };
extern const char MyString[] = "Hello World";
S<MyString> s;  // works now

If this stil doesn’t work, your compiler is broken :blink: