Solved

Run time type info on a simple datatype (e.g. int, char)

Posted on 2001-06-20
27
242 Views
Last Modified: 2006-11-17
Hi,

I have a template class which is used to store variables and then print them as strings

what I want is to have my class produce the string to represent the type automatically

Currently an instance of the class must be declared as
CValue<int> foo("Name", "int", 56);
I would like to reduce that to
CValue<int> foo("Name", 56);

the ouput from both functions should be
<Name type="int">56</Name>

This means having a function to get the "int" from <int>

what I was trying is

/////////////////////////////////////
template <class _T>
std::string GetType(_T me)
{
     if (int i = dynamic_cast<int>(me))
     {
          return std::string("int");
     }
     else if(char c = dynamic_cast<char>(me))
     {
          return std::string("char");
     }

     return "";
}
///////////////////////////////////////////

this of course doesn't work since dynamic_cast isn't designed for that sort of thing

Can anyone give me a way of getting this function to work?

i.e. a function like below
int a;
std::string s = GetType(a);
// s = "int"
char c;
s = GetType(c);
// s = "char"

    Vin

0
Comment
Question by:vfinn
  • 8
  • 8
  • 5
  • +4
27 Comments
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 6211026
This is the type of programming RTTI (runtime type information) is designed for:

#include <iostream>
#include <string>

using namespace std;

template <class T>
string Info(const T& t)
{
     string result;
     const type_info& i = typeid(t);
     result = i.name();
     return result;
}


int main(int argc, char* argv[])
{
     int c = 3;    

     cout << Info(c) << endl;

     return 0;
}

0
 

Author Comment

by:vfinn
ID: 6211126
Sorry, I should have mentioned in the question that RTTI isn't an option for me

The code is part of a large project and I don't intend to switch on RTTI for it as there is an associated hit which I can't have affecting all the other code


   Vin

Another thing I should mention is that it can be done, I think, using sizeof() but I am looking for a better solution than that since sizeof() leaves you open to overlap between variables

0
 
LVL 30

Accepted Solution

by:
Axter earned 300 total points
ID: 6211149
Can you use overloaders?

std::string GetType(int data){return "int";};
std::string GetType(char* data){return "char*";};
std::string GetType(char data){return "char";};
0
Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

 

Author Comment

by:vfinn
ID: 6211220
I suppose I could and it is certainly a nicer solution than using sizeof() but I was hoping for a catch all solution with the templates
maybe I'm over-complicating things

If no one comes up with a template'd solution I'll give you the points since that hadn't occurred to me :-)
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6211319
int a;
char b;

std::cout << typeid(a).name() << std::endl;

best regards
Andrey
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6211333
excuse me...
I read the anwers not carefully..
Reject please the answer
0
 
LVL 30

Expert Comment

by:Axter
ID: 6211386
Hi (Andrey_Kulik ) , welcome to Experts-Exchange.
All of the experts here, for the most part have learn from other experts as to the proper etiquette for posting answer.

Proper Etiquette for posting Answers:
1.  An answer should not be posted as an answer, if other experts have previously posted possible answers as comments, and/or have already made contributions to the question.

2.  An answer should not be posted as an answer, if it has a question.
Example: (Is this for windows? If so, here?s the answer)

3.  An answer should not be posted as an answer, if it has the phrase ?I think?.
Example:  (I think this should work)

4.  Full complete schoolwork answers must not be posted. (EE Policy)

5.  If you inadvertently post an answer after anther expert just post the same answer as a comment, you should promptly notify the questioner of your accidental post, and ask the questioner to fairly award the question to the expert whom fully/best answered the question first.  You might consider also apologizing to the other expert.

If you feel you have an answer, you can post it as a comment, and the questioner can convert your comment to an answer if he/she thinks it?s correct or deserving of the awarded points.

There are many experts who never post answers as answer.  Instead, they post their answers as comments.
If you read the following link, you?ll see why this is the preferred method for many of our valued experts, including myself.

http://www.experts-exchange.com/jsp/cmtyQuestAnswer.jsp

Hi (vfinn):
Feel free to click the [Reject Answer] button near (Answer-poster's) response, even if it seems like a good answer.
Doing so will increase your chance of obtaining additional input from other experts.  Later, you can click the [Select Comment as Answer] button on any response.
0
 

Author Comment

by:vfinn
ID: 6211426
Same answers a thui gave
0
 
LVL 1

Expert Comment

by:agomes
ID: 6211443
Once in your template solution you have to provide the type you want (the <int> in the CValue<int> foo("Name", 56)), why don't you provide a string with the type name and use va_list/va_start/va_arg() to get the value?

GetType( char *szType, ...)
{
    va_list vl;
    va_start( vl, szType );

    switch( szType )        
    {
        case 'i':
            // s = "int"
            (...)
     }
(...)
}
0
 

Author Comment

by:vfinn
ID: 6211497
Hi agomes,

I was supplying a string with the type name
CValue<int> foo("Name", "int", 45);
the second arg is the type
This is what I am trying to get away from.
Unless I have completely misunderstood what you were saying !
0
 
LVL 1

Expert Comment

by:agomes
ID: 6211693
What I meant is that you do not have to provide two times the type, once in the template, again as a string in the arguments. You can provide it only as an argument, and use va_arg() to get the value.

So, instead of CValue<int>("Name", 56), you can use CValue("Name", "int", 56) (no template class).

Actually you do not have to use variable arguments to get the value, but typecast a void*.

This way you can drop the type needed for the template. I don't know how to use only this type and drop the other one, without using RTTI, of course.
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6211711
Hi
I hope this helps

BUT

try this source in another then VC6.0 compiler
because
  template<>
    class typeInfo<C*> : public typeInfo<void*>
fail

i dont' know why.. IMHO it's a bug



template<class C>
class typeInfo
{
public:
     typedef C type;

    bool operator==(const typeInfo<class C> &t) const { return t::type == type; }
    bool operator!=(const typeInfo<class C> &t) const { return t::type != type; }

     string name() { return "undefined"; }
};

template<>
class typeInfo<void*>
{
public:
     string name() { return "pointer to void"; }
};

template<>
class typeInfo<C*> : public typeInfo<void*>
{
public:
     string name()
     {
          typeInfo<C> a;
          string s("pointer to ");
          s += a.name();
          return s;
     }
};

class typeInfo<int>
{
public:
     string name() { return "int"; }
};

class typeInfo<char>
{
public:
     string name() { return "char"; }
};

class typeInfo<bool>
{
public:
     string name() { return "bool"; }
};

template<class T>
string getName(T a)
{
     typeInfo<T> t;
     return t.name();
}


void main(void)
{
     int a;
     char b;
     int* c;
     cout << getName(a) << endl;
     cout << getName(b) << endl;
     cout << getName(c) << endl;
}


Andrey
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6211733
cout << getName(c) << endl;
"undefined"

but normal C++ compiler the output should be "pointer to int"

0
 

Author Comment

by:vfinn
ID: 6211735
but to do that I then have to store the value using a void* star which is inefficient in memory terms and I'm not sure how well the stream operator (<<) will work with that, and I need the stream.

I'd rather stick with the template than go with void*

0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6211762
the alternative way of template pointer definition is

class typeInfo<C*>
{
public:
    string name()
    {
         typeInfo<C> a;
         string s("pointer to ");
         s += a.name();
         return s;
    }
};

but in this case the source don't work also.

i'm thinking ...



0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6211769
you could define specialization for each case

class typeInfo<int*>
{ ... }

but it's bad

class typeInfo<C*>
{ ... }
really MUST work correct
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6211803
Alternative way (it work fine)

comby overloading and template


class typeInfo
{
public:
     string name(int) { return "int"; }
     string name(char) { return "char"; }
     string name(bool) { return "bool"; }

     template<class C> string name(C*)
     {
          string s("pointer to ");
          C c;
          s += name(c);
          return s;
     }
};

void main()
{
  int a;
  char b;
  int* c;

  typeInfo t;
     
  cout << t.name(a) << endl;
}
     cout << t.name(b) << endl;
     cout << t.name(c) << endl;
0
 
LVL 6

Expert Comment

by:thienpnguyen
ID: 6212700
Refine  Axter's comment .

#include <iostream>
using namespace std;

#define Create_GetType(T)  const char * GetType(T) { return #T; }

// Create overload functions

Create_GetType(int);
Create_GetType(float);
Create_GetType(double);
Create_GetType(char *);


// driver for testing.

void main()
{
    int i;
    float f;
    double d;
    char *p;

    cout << GetType(i) << endl;
    cout << GetType(f) << endl;
    cout << GetType(d) << endl;
    cout << GetType(p) << endl;
}


The output is

          int
          float
          double
          char *
0
 
LVL 1

Expert Comment

by:hakob
ID: 6213081
The best way is to use C++ typeid() operator.

typeid( type-id )

typeid( expression )

The typeid operator allows the type of an object to be determined at run-time.

The result of a typeid expression is a const type_info&. The value is a reference to a type_info object that represents either the type-id or the type of the expression, depending on which form of typeid is used. See for more information.


The type_info class describes type information generated within the program by the compiler. Objects of this class effectively store a pointer to a name for the type and an encoded value suitable for comparing two types for equality or collating order. The encoding rules and collating sequence for types are unspecified and may differ between programs.

class type_info {
public:
   virtual ~type_info();
   int operator==(const type_info& rhs) const;
   int operator!=(const type_info& rhs) const;
   int before(const type_info& rhs) const;
   const char* name() const;
   const char* raw_name() const;
private:
   ...
};


Below is the sample code


#include <string>
#include <iostream.h>

template <class _T>

std::string GetType(_T me)
{
    const type_info& ti = typeid(me);
    return ti.name();
}

int main(int argc, char* argv[])
{
     int i= 10;
     char c = 'a';

     cout << i << " , " << GetType(i).c_str() << endl;
     cout << c << " , " << GetType(c).c_str() << endl;
     return 0;
}


0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6213346
thienpnguyen: this class is better... try this :)

class typeInfo
{
public:
    string name(int) { return "int"; }
    string name(char) { return "char"; }
    string name(bool) { return "bool"; }

    template<class C> string name(C*)
    {
         C c;
         string s = name(c);
         s += "*";
         return s;
    }
};

void main()
{
 int* c;

 typeInfo t;
   
 cout << t.name(c) << endl;
}

0
 
LVL 30

Expert Comment

by:Axter
ID: 6213703
Hi hakob, welcome to EE.
All of the experts here, for the most part have learn from other experts as to the proper etiquette for posting answer.

An answer should not be posted as an answer, if other experts have previously posted possible answers as comments, and/or have already made contributions to the question.

There are many experts who never post answers as answer.  Instead, they post their answers as comments.
If you read the following link, you'll see why this is the preferred method for many of our valued experts, including myself.

http://www.experts-exchange.com/jsp/cmtyQuestAnswer.jsp
.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6213709
hakob,
In the future, please read all the comments before posting your answer.
This questioner already stated that he/she did not want to use typeid.
0
 

Author Comment

by:vfinn
ID: 6213719
I already rejected using RTTI
0
 

Author Comment

by:vfinn
ID: 6213798
I already rejected using RTTI
0
 

Author Comment

by:vfinn
ID: 6213807
Hi,

All the answers seem to be using variations on the basic overloading but the template versions are a bit to messy for pratical use so I'll clode the question out by accepting the original overload answer from Axter

Thanks for all the suggestion, Vin
0
 
LVL 30

Expert Comment

by:Axter
ID: 6213823
Thanks
0

Featured Post

Is Your AD Toolbox Looking More Like a Toybox?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question