Determining a variable's type

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steve Brown

    Determining a variable's type

    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.)
    }

    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.

  • John Harrison

    #2
    Re: Determining a variable's type


    "Steve Brown" <Do@not.spam> wrote in message
    news:4170DE74.6 060207@not.spam ...[color=blue]
    > 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.)
    > }[/color]

    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<doubl e>
    {
    enum { value = 3 };
    };

    template <class T>
    Object::Object( int TypeCode, T* data)
    {
    switch (TypeCode)
    {
    case 1:
    if (TypeToInt<T>:: value == 1)
    ...
    }
    [color=blue]
    >
    > 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.
    >[/color]

    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


    Comment

    • Steve Brown

      #3
      Re: Determining a variable's type

      John Harrison wrote:[color=blue]
      > "Steve Brown" <Do@not.spam> wrote in message
      > news:4170DE74.6 060207@not.spam ...
      >[color=green]
      >>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::Objec t(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.)
      >>}[/color]
      >
      >
      > 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<doubl e>
      > {
      > enum { value = 3 };
      > };
      >
      > template <class T>
      > Object::Object( int TypeCode, T* data)
      > {
      > switch (TypeCode)
      > {
      > case 1:
      > if (TypeToInt<T>:: value == 1)
      > ...
      > }
      >
      >[color=green]
      >>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::Objec t(int TypeCode, int* data)
      >>{ if(TypeCode != 1)
      >>{ //Error
      >>} }
      >>
      >>Object::Objec t(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.
      >>[/color]
      >
      >
      > 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
      >
      >[/color]

      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

      Comment

      • John Harrison

        #4
        Re: Determining a variable's type


        "Steve Brown" <Do@not.spam> wrote in message
        news:417101AB.8 040103@not.spam ...[color=blue]
        > John Harrison wrote:[color=green]
        >> "Steve Brown" <Do@not.spam> wrote in message
        >> news:4170DE74.6 060207@not.spam ...
        >>[color=darkred]
        >>>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::Obje ct(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.)
        >>>}[/color]
        >>
        >>
        >> 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<doubl e>
        >> {
        >> enum { value = 3 };
        >> };
        >>
        >> template <class T>
        >> Object::Object( int TypeCode, T* data)
        >> {
        >> switch (TypeCode)
        >> {
        >> case 1:
        >> if (TypeToInt<T>:: value == 1)
        >> ...
        >> }
        >>
        >>[color=darkred]
        >>>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::Obje ct(int TypeCode, int* data)
        >>>{ if(TypeCode != 1)
        >>>{ //Error
        >>>} }
        >>>
        >>>Object::Obje ct(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.
        >>>[/color]
        >>
        >>
        >> 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
        >>
        >>[/color]
        >
        > 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
        >[/color]

        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


        Comment

        Working...