Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 251
  • Last Modified:

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

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
vfinn
Asked:
vfinn
  • 8
  • 8
  • 5
  • +4
1 Solution
 
Tommy HuiEngineerCommented:
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
 
vfinnAuthor Commented:
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
 
AxterCommented:
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
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
vfinnAuthor Commented:
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
 
Andrey_KulikCommented:
int a;
char b;

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

best regards
Andrey
0
 
Andrey_KulikCommented:
excuse me...
I read the anwers not carefully..
Reject please the answer
0
 
AxterCommented:
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
 
vfinnAuthor Commented:
Same answers a thui gave
0
 
agomesCommented:
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
 
vfinnAuthor Commented:
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
 
agomesCommented:
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
 
Andrey_KulikCommented:
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
 
Andrey_KulikCommented:
cout << getName(c) << endl;
"undefined"

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

0
 
vfinnAuthor Commented:
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
 
Andrey_KulikCommented:
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
 
Andrey_KulikCommented:
you could define specialization for each case

class typeInfo<int*>
{ ... }

but it's bad

class typeInfo<C*>
{ ... }
really MUST work correct
0
 
Andrey_KulikCommented:
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
 
thienpnguyenCommented:
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
 
hakobCommented:
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
 
Andrey_KulikCommented:
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
 
AxterCommented:
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
 
AxterCommented:
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
 
vfinnAuthor Commented:
I already rejected using RTTI
0
 
vfinnAuthor Commented:
I already rejected using RTTI
0
 
vfinnAuthor Commented:
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
 
AxterCommented:
Thanks
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 8
  • 8
  • 5
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now