Re: Convert template argument to string
On Oct 16, 9:57 am, "Marco Nef" <maill...@shima.ch> wrote:
I'm looking for a template class that converts the template argument =
to
a
string, so something like the following should work:
Convert<float>::Get() == "float";
Convert<3>::Get() == "3";
Convert<HelloWorld>::Get() == "HelloWorld";
The reason I need this is that in our design every class of a certain
hierarchy has a class name that must be unique. So far I could not fi=
nd
a
solution for template classes.
What do you need those names for? Why do you want for it to work with
values as well as with types?
If typeid(X).name() is not sufficient for you (not portable, may be
not human readable), you'll have to provide a string for every class
yourself.
Thanks for your replies. I know about typeid and it is not sufficient as
"typeid->name" by the standard is not persistent and not even unique. The
macro "TOSTRING(x) #x" does not work because it is evaluated before the
template process works. This means that "Convert<float>::Get()" returns
"Type" if Type is the name of the template argument.
Another solution would be the following:
template<typename Type> struct Convert
{
const String &GetName(VOID) const { return Type::GetName(); }};
template<> struct Convert<float>
{
const String &GetName(VOID) const { return "float"; }};
template<> struct Convert<int>
{
const String &GetName(VOID) const { return "int"; }
};
and so on...
Please note, that in C++ you don't need (void) for functions with no
arguments. () is sufficient.
These GetName() functions return a reference to a non-existent
constant String, which is a programming error.
So any classes provided as template argument need to implement GetName(),
for the base types there are specializations. This works, but I don't rea=
lly
like it.
You don't really need to provide a name for each specialisation,
because it can be generated in a generic fashion. Here is an example:
#include <string>
#include <iostream>
template<class T>
struct TypeName
{
static std::string get() { return T::typeName(); }
};
// add more specialisations for the build-in types
template<> std::string TypeName<int>::get() { return "int"; }
struct A
{
static std::string typeName() { return "A"; }
};
template<class T>
struct B
{
static std::string typeName() { return "B<" +
TypeName<T>::get() + ">"; }
};
int main()
{
std::cout << TypeName<int>::get() << '\n';
std::cout << TypeName<A>::get() << '\n';
std::cout << TypeName<B<int> >::get() << '\n';
std::cout << TypeName<B<A> >::get() << '\n';
std::cout << TypeName<B<B<B<int> > > >::get() << '\n';
}
Output:
int
A
B<int>
B<A>
B<B<B<int>>>
--
Max