'typeid' versus 'typeof' in C++
Asked Answered
C

7

202

I am wondering what the difference is between typeid and typeof in C++. Here's what I know:

  • typeid is mentioned in the documentation for type_info which is defined in the C++ header file typeinfo.

  • typeof is defined in the GCC extension for C and in the C++ Boost library.

Also, here is test code test that I've created where I've discovered that typeid does not return what I expected. Why?

main.cpp

#include <iostream>  
#include <typeinfo>  //for 'typeid' to work  

class Person {  
    public:
    // ... Person members ...  
    virtual ~Person() {}  
};  

class Employee : public Person {  
    // ... Employee members ...  
};  

int main () {  
    Person person;  
    Employee employee;  
    Person *ptr = &employee;  
    int t = 3;  

    std::cout << typeid(t).name() << std::endl;  
    std::cout << typeid(person).name() << std::endl;   // Person (statically known at compile-time)  
    std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time)  
    std::cout << typeid(ptr).name() << std::endl;      // Person * (statically known at compile-time)  
    std::cout << typeid(*ptr).name() << std::endl;     // Employee (looked up dynamically at run-time  
                                                       // because it is the dereference of a pointer
                                                       // to a polymorphic class)  
 }  

output:

bash-3.2$ g++ -Wall main.cpp -o main  
bash-3.2$ ./main   
i  
6Person  
8Employee  
P6Person  
8Employee
Caucasoid answered 31/12, 2009 at 17:55 Comment(3)
In what way do you think your code doesn't print the right type names? It looks good to me. The actual string returned by name() is implementation-defined. It doesn't have to be a valid C++ identifier name, just something that uniquely identifies the type. Looks like your implementation uses the compiler's general name-mangling scheme.Piggin
Thanks Rob! I was expecting those exactly same as type names as I saw in en.wikipedia.org/wiki/Typeid. What can name-mangling do here?Caucasoid
If you are new to typeid like me: You need a virtual function in the base type to turn on the vtable or the last line will print the base type.Whisenant
E
258

C++ language has no such thing as typeof. You must be looking at some compiler-specific extension. If you are talking about GCC's typeof, then a similar feature is present in C++11 through the keyword decltype. Again, C++ has no such typeof keyword.

typeid is a C++ language operator which returns type identification information at run time. It basically returns a type_info object, which is equality-comparable with other type_info objects.

Note, that the only defined property of the returned type_info object has is its being equality- and non-equality-comparable, i.e. type_info objects describing different types shall compare non-equal, while type_info objects describing the same type have to compare equal. Everything else is implementation-defined. Methods that return various "names" are not guaranteed to return anything human-readable, and even not guaranteed to return anything at all.

Note also, that the above probably implies (although the standard doesn't seem to mention it explicitly) that consecutive applications of typeid to the same type might return different type_info objects (which, of course, still have to compare equal).

Ethelda answered 31/12, 2009 at 18:11 Comment(5)
wouldnt this need an update since C++11 has decltype ? I am not sure what is the general policy, but as the question is tagged C++ I would expect it to refer to the latest standard. Retagging the question as C++03 would also be an option imho. I personally get quite confused sometimes, as I have to use preC++11 at work and sometimes I am not sure what is true "pre11" or "post11".Bismuthic
FYI, decltype is not a replacement for typeof. typeof works on types too while decltype doesn't. For example, typeof(int) is int while decltype(int) is an error.Pease
"type_info objects describing different types shall compare non-equal". Actually, this isn't guaranteed. The inequality operator was removed in C++20 to (I assume) discourage relying on different types comparing non-equal. But if you think about it, equality isn't safe if inequality isn't safe.Strike
@IndianaKernick Your link points to hash_code, which is unrelated to equality because hash functions do not have to guarantee to be free of collisions to be useful.Statuette
@Pease I found another difference: decltype will preserve reference types while typeof will remove them. For example, with int& x;, typeof(x) will give int while decltype(x) will give int&. I found this thread while searching why typeof seemed to cast away reference types.Bicker
W
63

The primary difference between the two is the following

  • typeof is a compile time construct and returns the type as defined at compile time
  • typeid is a runtime construct and hence gives information about the runtime type of the value.

typeof Reference: http://www.delorie.com/gnu/docs/gcc/gcc_36.html

typeid Reference: https://en.wikipedia.org/wiki/Typeid

Whiplash answered 31/12, 2009 at 18:1 Comment(2)
Thank you, JaredPar! I have some new questions in the updated post after reading your replies. Such as if it is also true that their returns are used for different purposes: the return of typeof is used as type keyword that can define variable, but the return of typeid cannot?Caucasoid
first link is no longer working ( send to gnu.org ).Etrem
G
28

typeid can operate at runtime, and return an object describing the run time type of the object, which must be a pointer to an object of a class with virtual methods in order for RTTI (run-time type information) to be stored in the class. It can also give the compile time type of an expression or a type name, if not given a pointer to a class with run-time type information.

typeof is a GNU extension, and gives you the type of any expression at compile time. This can be useful, for instance, in declaring temporary variables in macros that may be used on multiple types. In C++, you would usually use templates instead.

Germangermana answered 31/12, 2009 at 18:1 Comment(3)
As far as I know, typeid will accept any expression, not just those that evaluate to objects with virtual methods. Furthermore, typeid will accept a type name, not just an expression. You can say typeid(5) or typeid(std::string) if you want.Piggin
I've clarified my answer to make that clear; typeid can return run-time type information if available, but will provide compile time type information for anything else.Germangermana
Thank you, Brian and Rob! I have some new questions in the updated post after reading your replies.Caucasoid
A
27

Answering the additional question:

my following test code for typeid does not output the correct type name. what's wrong?

There isn't anything wrong. What you see is the string representation of the type name. The standard C++ doesn't force compilers to emit the exact name of the class, it is just up to the implementer(compiler vendor) to decide what is suitable. In short, the names are up to the compiler.


These are two different tools. typeof returns the type of an expression, but it is not standard. In C++0x there is something called decltype which does the same job AFAIK.

decltype(0xdeedbeef) number = 0; // number is of type int!
decltype(someArray[0]) element = someArray[0];

Whereas typeid is used with polymorphic types. For example, lets say that cat derives animal:

animal* a = new cat; // animal has to have at least one virtual function
...
if( typeid(*a) == typeid(cat) )
{
    // the object is of type cat! but the pointer is base pointer.
}
Anemone answered 31/12, 2009 at 18:6 Comment(1)
Thank you, Arak! I just updated the post with some new questions. Please take a look if possible.Caucasoid
A
5

typeid provides the type of the data at runtime, when asked for. Typedef is a compile time construct that defines a new type as stated after that. There is no typeof in C++ Output appears as (shown as inscribed comments):

std::cout << typeid(t).name() << std::endl;  // i
std::cout << typeid(person).name() << std::endl;   // 6Person
std::cout << typeid(employee).name() << std::endl; // 8Employee
std::cout << typeid(ptr).name() << std::endl;      // P6Person
std::cout << typeid(*ptr).name() << std::endl;     //8Employee
Auberbach answered 3/10, 2014 at 3:26 Comment(0)
G
3

You can use Boost demangle to accomplish a nice looking name:

#include <boost/units/detail/utility.hpp>

and something like

To_main_msg_evt ev("Failed to initialize cards in " + boost::units::detail::demangle(typeid(*_IO_card.get()).name()) + ".\n", true, this);
Gosport answered 3/10, 2014 at 3:21 Comment(0)
T
1

Although as top commenter pointed out, there is no such thing as typeof in C++, you can leverage function overloads to make a faux typeof function:

const char *type_of(int x){return “int”;}
const char *type_of(const char *x){return “const char*”;}

Of course, this is could be extended upon to also use other data types. I’m newer to C++, so there may be some issues with it, such as errors at runtime, however in my use case of using template params and descerning an int from a float, for example, was straightforward.

Optimizations: It would probably be better for the overloaded function to return a short as opposed to const char *’s for the sake of memory efficiency, which then could be compared to another short, or plugged into a hash table for the string representation.

Teratism answered 13/1, 2023 at 20:11 Comment(2)
Not correct. There's a GNU extension which provides typeof and standard C++ has __typeof__ and typeidHillis
Problem is…what it produces is often not descriptive enough. typeid(int) returns “i”Teratism

© 2022 - 2025 — McMap. All rights reserved.