Solved

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

Posted on 2001-06-20
27
240 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 

Author Comment

by:vfinn
Comment Utility
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
Comment Utility
int a;
char b;

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

best regards
Andrey
0
 
LVL 2

Expert Comment

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

Expert Comment

by:Axter
Comment Utility
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
Comment Utility
Same answers a thui gave
0
 
LVL 1

Expert Comment

by:agomes
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
cout << getName(c) << endl;
"undefined"

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

0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:vfinn
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
I already rejected using RTTI
0
 

Author Comment

by:vfinn
Comment Utility
I already rejected using RTTI
0
 

Author Comment

by:vfinn
Comment Utility
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
Comment Utility
Thanks
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
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 how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

763 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

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now