By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,712 Members | 1,591 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,712 IT Pros & Developers. It's quick & easy.

How to capture the name of a class in a string at compile time ?

P: n/a
I have a class defined by a template which needs to "say" its type to the
user via string.

As an example, here is the class that I want to fix :

template<class T> class Container : public Serializable
{
public:

T value;

static string classIdentifier;

string& getClassIdentifier();

};

template <class T> string& Container<T>::getClassIdentifier()
{
return classIdentifier;
}
For now, the only way I found to initiliaze the string is with :

string Container<bool>::classIdentifier("Container<bool>" );
string Container<char>::classIdentifier("Container<char>" );
string Container<short>::classIdentifier("Container<short >");
string Container<int>::classIdentifier("Container<int>");
string Container<float>::classIdentifier("Container<float >");
string Container<double>::classIdentifier("Container<doub le>");
string Container<unsigned char>::classIdentifier("Container<unsigned
char>");
string Container<unsigned short>::classIdentifier("Container<unsigned
short>");
string Container<unsigned int>::classIdentifier("Container<unsigned int>");
string Container<unsigned float>::classIdentifier("Container<unsigned
float>");
string Container<unsigned double>::classIdentifier("Container<unsigned
double>");

This solution works for the basis types, but now imagine that I would like
to use my template class with another type which is not in the list ? The
compiler will say that my static variable is not defined :-(

I think there might be a way to do it with a macro but I don't know how to
do. Does someone here have a solution ?

Vincent
Jul 22 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a

"Vincent Cantin" <MY***************@astrocorp.com.tw> wrote in message
news:2k************@uni-berlin.de...
I have a class defined by a template which needs to "say" its type to the
user via string.

As an example, here is the class that I want to fix :

template<class T> class Container : public Serializable
{


There is no guaranteed way of doing this, but the following might work on
some compilers

#include <type_info>

template<class T> class Container : public Serializable
{
public:
std::string getClassIdentifier() const
{
return typeid(T).name();
}
...

The problem is that the C++ standard does not make any guarantees as to what
the name() method returns, but some compilers implement it to return a human
readable name.

john
Jul 22 '05 #2

P: n/a

"Vincent Cantin" <MY***************@astrocorp.com.tw> wrote in message news:2k************@uni-berlin.de...
I have a class defined by a template which needs to "say" its type to the
user via string.

As an example, here is the class that I want to fix :

template<class T> class Container : public Serializable
{
public:

T value;

static string classIdentifier;

string& getClassIdentifier();

};

template <class T> string& Container<T>::getClassIdentifier()
{
return classIdentifier;
}
For now, the only way I found to initiliaze the string is with :

string Container<bool>::classIdentifier("Container<bool>" );
string Container<char>::classIdentifier("Container<char>" );
string Container<short>::classIdentifier("Container<short >");
string Container<int>::classIdentifier("Container<int>");
string Container<float>::classIdentifier("Container<float >");
string Container<double>::classIdentifier("Container<doub le>");
string Container<unsigned char>::classIdentifier("Container<unsigned
char>");
string Container<unsigned short>::classIdentifier("Container<unsigned
short>");
string Container<unsigned int>::classIdentifier("Container<unsigned int>");
string Container<unsigned float>::classIdentifier("Container<unsigned
float>");
string Container<unsigned double>::classIdentifier("Container<unsigned
double>");

This solution works for the basis types, but now imagine that I would like
to use my template class with another type which is not in the list ? The
compiler will say that my static variable is not defined :-(

I think there might be a way to do it with a macro but I don't know how to
do. Does someone here have a solution ?

Vincent


If you are using GNU g++ version 3.3
the following method can be used.

========= C++ code : foo.cpp : BEGIN =========
#include <string>
#include <iostream>
using namespace std;

template<class T>
class Container
{
public:

static const string classIdentifier;
static string getClassIdentifier();
};

template<class T>
string Container<T>::getClassIdentifier()
{
const string str0 (__PRETTY_FUNCTION__);
string str1 (str0.substr (0, str0.find ("<")));
str1 = str1.substr (str1.find_last_of (' ') + 1);
string str2 (str0.substr (str0.find_last_of (' ') + 1));
str2 = str2.substr (0, str2.size() - 1);

return str1 + "<" + str2 + ">";
}

template<class T>
const string Container<T>::classIdentifier(Container<T>::getCla ssIdentifier());

class Foo {};
template<class T>
class Bar {};
int main ()
{
cout << Container<bool>::classIdentifier << endl;
cout << Container<int>::classIdentifier << endl;
cout << Container<Foo>::classIdentifier << endl;
cout << Container<Bar<int> >::classIdentifier << endl;
cout << Container<Bar<Foo> >::classIdentifier << endl;

cout << endl;
cout << Container<bool>().classIdentifier << endl;
cout << Container<int>().classIdentifier << endl;
cout << Container<Foo>().classIdentifier << endl;
cout << Container<Bar<int> >().classIdentifier << endl;
cout << Container<Bar<Foo> >().classIdentifier << endl;
return 0;
}
========= C++ code : foo.cpp : END ===========
========= Compilation & Run : BEGIN =========

$ g++ --version
g++ (GCC) 3.3.1 (cygming special)
[snip]

$ g++ foo.cpp

$ a

Container<bool>
Container<int>
Container<Foo>
Container<Bar<int>>
Container<Bar<Foo>>

Container<bool>
Container<int>
Container<Foo>
Container<Bar<int>>
Container<Bar<Foo>>

========= Compilation & Run : END ===========
--
Alex Vinokur
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn

Jul 22 '05 #3

P: n/a
Alex Vinokur wrote:
"Vincent Cantin" <MY***************@astrocorp.com.tw> wrote in message news:2k************@uni-berlin.de...

If you are using GNU g++ version 3.3
the following method can be used. [...] template<class T>
string Container<T>::getClassIdentifier()
{
const string str0 (__PRETTY_FUNCTION__);
string str1 (str0.substr (0, str0.find ("<")));
str1 = str1.substr (str1.find_last_of (' ') + 1);
string str2 (str0.substr (str0.find_last_of (' ') + 1));
str2 = str2.substr (0, str2.size() - 1);

return str1 + "<" + str2 + ">";
}


Or you could go for something a little more generic:
(__FUNCSIG__ is msvc7 specific, I assume gcc's __PRETTY_FUNCTION__ would
be similar)

#include <iostream>
#include <string>

/*d::string typestring< <- must be same length */
std::string dummy(void) { return __FUNCSIG__; }

template <typename T>
std::string typestring(void)
{
std::string n = __FUNCSIG__ + dummy().size();
return n.erase(n.rfind('>'));
}

struct etc { };

template<class T> class Container { };

int main(void)
{
std::cout << typestring<int>() << '\n';
std::cout << typestring<std::string>() << '\n';
std::cout << typestring<etc>() << '\n';
std::cout << typestring<Container<Container<int> > >() << '\n';
}

Result:

int
class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >
struct etc
class Container<class Container<int> >

Personally, I'd probably go for something more tedious but standard.

-josh

Jul 22 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.