Jump to content


Getting template parameter as string


7 replies to this topic

#1 Alex

    Valued Member

  • Members
  • PipPipPip
  • 152 posts

Posted 15 March 2007 - 03:04 PM

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

#2 dave_

    Senior Member

  • Members
  • PipPipPipPip
  • 584 posts

Posted 15 March 2007 - 07:23 PM

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

#3 Reedbeta

    DevMaster Staff

  • Administrators
  • 5307 posts
  • LocationBellevue, WA

Posted 15 March 2007 - 08:58 PM

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.
reedbeta.com - developer blog, OpenGL demos, and other projects

#4 Alex

    Valued Member

  • Members
  • PipPipPip
  • 152 posts

Posted 15 March 2007 - 09:14 PM

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

#5 dave_

    Senior Member

  • Members
  • PipPipPipPip
  • 584 posts

Posted 16 March 2007 - 12:19 AM

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.

#6 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 16 March 2007 - 12:36 AM

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 :)
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.

#7 Alex

    Valued Member

  • Members
  • PipPipPip
  • 152 posts

Posted 16 March 2007 - 02:13 PM

@.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

#8 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 16 March 2007 - 04:13 PM

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:
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users