Re: Determining a variable's type

From: John Harrison (john_andronicus_at_hotmail.com)
Date: 10/16/04


Date: Sat, 16 Oct 2004 13:17:06 +0100


"Steve Brown" <Do@not.spam> wrote in message
news:417101AB.8040103@not.spam...
> John Harrison wrote:
>> "Steve Brown" <Do@not.spam> wrote in message
>> news:4170DE74.6060207@not.spam...
>>
>>>Hello all,
>>>
>>>Is there a way to determine a variable's type at run-time? The reason
>>>I'm asking is that i have code that looks like this:
>>>
>>>template <class T>
>>>Object::Object(int TypeCode, T* data)
>>>{ switch (TypeCode)
>>>case 1:
>>>//Check to see if data is correct type, //according to a lookup table of
>>>my own (1 is //int, 2 for char, etc.)
>>>}
>>
>>
>> Yuck, yuck. But if you really need this
>>
>> template <class T>
>> class TypeToInt
>> {
>> // value deliberately undefined
>> };
>>
>> template <>
>> class TypeToInt<int>
>> {
>> enum { value = 1 };
>> };
>>
>> template <>
>> class TypeToInt<char>
>> {
>> enum { value = 2 };
>> };
>>
>> template <>
>> class TypeToInt<double>
>> {
>> enum { value = 3 };
>> };
>>
>> template <class T>
>> Object::Object(int TypeCode, T* data)
>> {
>> switch (TypeCode)
>> {
>> case 1:
>> if (TypeToInt<T>::value == 1)
>> ...
>> }
>>
>>
>>>So, I will pass the function a pointer to a variable of a particular
>>>type, and a numeric code representing what that type is. I want to make
>>>sure the code and the data match, and if not, return an error(probably
>>>just print some text, but that's not important). I know I can do this
>>>with manually overloaded constructors, like:
>>>
>>>Object::Object(int TypeCode, int* data)
>>>{ if(TypeCode != 1)
>>>{ //Error
>>>} }
>>>
>>>Object::Object(int TypeCode, char* data)
>>>{ if(TypeCode != 2)
>>>{ //Error
>>>} }
>>>
>>>But this can get big and complicated, and I'd rather not.
>>>Is there some alternate way to do this with inheritance, maybe, or is
>>>there a function that tells you, in some form, what type a variable is?
>>>Comparing to make sure two variables are the same type would work, too.
>>>
>>
>>
>> That's a little more elegant
>>
>> template <class T, class U>
>> class SameType
>> {
>> enum { value = 0 };
>> };
>>
>> template <class T>
>> class SameType<T, T>
>> {
>> enum { value = 1 };
>> };
>>
>> template <class T>
>> Object::Object(int TypeCode, T* data)
>> {
>> switch (TypeCode)
>> {
>> case 1:
>> if (SameType<T, int>::value)
>> ...
>> }
>>
>> But for this you need a compiler that supports partial template
>> specialisation and older compilers often don't.
>>
>> john
>>
>>
>
> The last solution looks like what I want, thanks! A couple questions,
> though. By saying template<class T, class U>, is it guarunteed that they
> will be different types? It seems that that must be true for this to
> work? Also, what part of this solution makes use of partial template
> specialization? It all seems pretty straightforward to me. Finally, why
> use an enum, and not just a bool?
>
> Thanks for your help,
> Steve
>

When you write 'SameType<X, Y>::value' the compiler has to choose between
the two versions of SameType. The first is the unspecialised version where X
and Y can be any type, the second is the partially specialised version where
X and Y must be the same type. The rules for which is chosen are complex,
but essentially it boils down to the compiler chooses the most specialised
version which can possibly apply. So, to answer your first question, T and U
could be the same type but for this particular code whenever T and U would
be the same type then the second version is chosen instead.

This is the part that uses partial specialisation.

template <class T>
class SameType<T, T>
{
    enum { value = 1 };
};

Its a template specialisation (because it specialises the previous SameType
template) but its not a full specialisation because there is still one
template parameter, namely T.

Incidentally there are ways to solve this without using partial template
specialisation so if your compiler chokes on the above, then I could show
you another method. VC++ 6 is the compiler that notoriously doesn't support
partial template specialisation.

Using enums is just personal preference. This is perfectly good and legal
C++

template <class T, class U>
class SameType
{
    static const bool value = false;
};

But some compilers have issues with that kind of code.

john



Relevant Pages

  • Re: .NET 2.0 to be launched on Nov 8
    ... Passing a non-type as a template parameter. ... But so are generics, ... the final specialisation for .NET also happens in the JIT. ... Since the compiler can semantically check ...
    (borland.public.delphi.non-technical)
  • Re: Class templates and friend function templates
    ... friend void process; ... each specialization of the `task' class template has all specializations of the function template `func' as friends. ... It only has one parameter that is distinct, thus implying a kind of partial specialisation of the friend declaration once C is instantiated for a particular type. ...
    (microsoft.public.vc.language)
  • Re: does not compile with "using namespace std"
    ... That means that a specialisation of class Stack for some ... template parameter T will have the following function ... because you haven't provided a definition for the friend operator <<. ...
    (comp.lang.cpp)
  • Re: Class templates and friend function templates
    ... >> Function template doesn't support partial specialization. ... > issue is the specialisation of the *friend declaration*, ... > appearance of allowing a partial specialisation of the ...
    (microsoft.public.vc.language)
  • Re: Implementing a templated "round" function?
    ... At the moment i have two different implementations, ... I did add a second template parameter S for the source type: ... > I could add a specialisation for every combination of S and T, ... template <typename T, typename S> ...
    (comp.lang.cpp)

Loading