C keyword typeid
has a magic: it know when to use compile-time type info and when to use runtime type info:
#include <iostream>
#include <typeinfo>
using namespace std;
struct Interface { virtual void f() = 0; };
struct S1 : Interface { void f() { cout << "S1\n"; }};
struct S3 : S1 { void f() { cout << "S3\n"; }};
int main() {
S1 s1;
cout << typeid(s1).name() << endl;
S1* ps = new S3;
cout << typeid(ps).name() << endl;
cout << typeid(*ps).name() << endl;
delete ps;
return 0;
}
The program prints:
struct S1
struct S1 * __ptr64
struct S3
My question: does gcc/clang compiler has any compiler macro, or type_traits : that exposes typeid
magic and tells us whether typeid(*ps)
is compile-time determined or runtime-determined?
CodePudding user response:
Check this out:
template<typename T>
constexpr auto my_typeId(const T& value) {
auto compileTimeChecked{ true };
const auto& typeId = typeid(compileTimeChecked = false, value);
return std::make_pair(compileTimeChecked, &typeId);
}
The first argument of the pair has true
if typeid
is resolved at compile time. false
otherwise. The second member points to the resolved information const std::type_info *
The trick here is that typeid
semantic changes depending on the argument it takes. If argument is an instance of a polymorphic class, then typeid
actually evaluates the expression in runtime, and the side effect of compileTimeChecked = false
comes into play. Otherwise typeid
does not evaluate the expression (thus, compileTimeChecked = false
never happens), but just takes the static type of value
resolved at compile-time.