Template question

S

Simon Elliott

Suppose I have a template:

template <class T> class bloggs
{
public:
T value;
};

Which I could use to store values of a particular type, eg
bloggs<unsigned short> b1;
b1.value = 1;

I want to extend this such that there's another data member, let's call
it bloggs_type, which is initialised to (some function of) the data
type I use when the class instance is created.

For example, if bloggs_type is a std::string:

bloggs<double> b2;
b2.value = 1.1;
std::cout << b2.bloggs_type << std::endl;

.... would output "double\n"

Is there any way I can do anything along those lines?
 
R

Rolf Magnus

Simon Elliott said:
Suppose I have a template:

template <class T> class bloggs
{
public:
T value;
};

Which I could use to store values of a particular type, eg
bloggs<unsigned short> b1;
b1.value = 1;

I want to extend this such that there's another data member, let's call
it bloggs_type, which is initialised to (some function of) the data
type I use when the class instance is created.

For example, if bloggs_type is a std::string:

bloggs<double> b2;
b2.value = 1.1;
std::cout << b2.bloggs_type << std::endl;

... would output "double\n"

Is there any way I can do anything along those lines?

There is the typeid, which returns an object with a name() member function.
The problem is that the name returned is not standardized. Some compilers
use the name as it would appear in the source code, others use the string
that would be used in name mangling. Others might even use another string.
If that doesn't matter much in your case, you could use it anyway, like:

template <class T> class bloggs
{
public:
T value;
std::string type() const;
};

std::string bloggs::type() const
{
return typeid(T).name();
}

If that isn't sufficient, you're out of luck. You'd need to explicitly
provide a string for the name of every type you want to use with your
template.
 
S

Simon Elliott

There is the typeid, which returns an object with a name() member
function. The problem is that the name returned is not standardized.
Some compilers use the name as it would appear in the source code,
others use the string that would be used in name mangling. Others
might even use another string. If that doesn't matter much in your
case, you could use it anyway, like:

template <class T> class bloggs
{
public:
T value;
std::string type() const;
};

std::string bloggs::type() const
{
return typeid(T).name();
}

If that isn't sufficient, you're out of luck. You'd need to explicitly
provide a string for the name of every type you want to use with your
template.

Thanks - I'd forgotten about typeid. I'm not sure this is the correct
solution in this case as the code must compile with a number of
compilers and for a number of platforms.

Do the preprocessor directives work with template type names?
 
R

Rolf Magnus

Simon Elliott said:
Thanks - I'd forgotten about typeid. I'm not sure this is the correct
solution in this case as the code must compile with a number of
compilers and for a number of platforms.

It depends. If you need to transfer the type names between programs compiled
by different compilers, it probably won't work. But in this case, you have
to care about a lot more, like structure member alignments or byte ordering
and different type sizes.
Do the preprocessor directives work with template type names?

No. Template instantiation - like everything else in the compiler - happens
after the preprocessing step. So if you use it, you'll just get "T" as name
for your classes.
 
P

Peter Koch Larsen

Simon Elliott said:
Suppose I have a template:

template <class T> class bloggs
{
public:
T value;
};

Which I could use to store values of a particular type, eg
bloggs<unsigned short> b1;
b1.value = 1;

I want to extend this such that there's another data member, let's call
it bloggs_type, which is initialised to (some function of) the data
type I use when the class instance is created.

For example, if bloggs_type is a std::string:

bloggs<double> b2;
b2.value = 1.1;
std::cout << b2.bloggs_type << std::endl;

... would output "double\n"

Is there any way I can do anything along those lines?

If you can't use typeid you have to supply your own name somewhere. You
could use a helper template-class for this:

template< typename t > class simons_names
 
P

Peter Koch Larsen

Simon Elliott said:
Suppose I have a template:

template <class T> class bloggs
{
public:
T value;
};

Which I could use to store values of a particular type, eg
bloggs<unsigned short> b1;
b1.value = 1;

I want to extend this such that there's another data member, let's call
it bloggs_type, which is initialised to (some function of) the data
type I use when the class instance is created.

For example, if bloggs_type is a std::string:

bloggs<double> b2;
b2.value = 1.1;
std::cout << b2.bloggs_type << std::endl;

... would output "double\n"

Is there any way I can do anything along those lines?

If you can't use typeid you'll have to supply your own names. One way to do
this would be to have a helper template-function - e.g.:

template< typename t >
std::string simons_name()
{
return "unknown";
// or whatever. you do not have to implement this - will give a
linkerror
}

template< >
std::string simons_name<int>()
{
return "int";
}


and so on. Now:

template <class T> class bloggs
{
public:
T value;
static std::string name() { return simons_name<T>(); }
};
 
S

Simon Elliott

If you can't use typeid you'll have to supply your own names. One way
to do this would be to have a helper template-function - e.g.:
[snip]

Thanks - I think that will give me the result I'm looking for.
 

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

Forum statistics

Threads
474,175
Messages
2,570,947
Members
47,498
Latest member
yelene6679

Latest Threads

Top