例如:
int a = 12;
cout << typeof(a) << endl;
预期的输出:
int
例如:
int a = 12;
cout << typeof(a) << endl;
预期的输出:
int
当前回答
注意,c++的RTTI特性生成的名称是不可移植的。 例如,类
MyNamespace::CMyContainer<int, test_MyNamespace::CMyObject>
将有以下名称:
// MSVC 2003:
class MyNamespace::CMyContainer[int,class test_MyNamespace::CMyObject]
// G++ 4.2:
N8MyNamespace8CMyContainerIiN13test_MyNamespace9CMyObjectEEE
所以不能将此信息用于序列化。但是typeid(a).name()属性仍然可以用于日志/调试目的
其他回答
我喜欢Nick的方法,一个完整的表单可能是这样的(对于所有基本数据类型):
template <typename T> const char* typeof(T&) { return "unknown"; } // default
template<> const char* typeof(int&) { return "int"; }
template<> const char* typeof(short&) { return "short"; }
template<> const char* typeof(long&) { return "long"; }
template<> const char* typeof(unsigned&) { return "unsigned"; }
template<> const char* typeof(unsigned short&) { return "unsigned short"; }
template<> const char* typeof(unsigned long&) { return "unsigned long"; }
template<> const char* typeof(float&) { return "float"; }
template<> const char* typeof(double&) { return "double"; }
template<> const char* typeof(long double&) { return "long double"; }
template<> const char* typeof(std::string&) { return "String"; }
template<> const char* typeof(char&) { return "char"; }
template<> const char* typeof(signed char&) { return "signed char"; }
template<> const char* typeof(unsigned char&) { return "unsigned char"; }
template<> const char* typeof(char*&) { return "char*"; }
template<> const char* typeof(signed char*&) { return "signed char*"; }
template<> const char* typeof(unsigned char*&) { return "unsigned char*"; }
正如Scott Meyers在《Effective Modern c++》中所解释的那样,
对std::type_info::name的调用不能保证返回任何有意义的东西。
最好的解决方案是让编译器在类型推断期间生成错误消息,例如:
template<typename T>
class TD;
int main(){
const int theAnswer = 32;
auto x = theAnswer;
auto y = &theAnswer;
TD<decltype(x)> xType;
TD<decltype(y)> yType;
return 0;
}
根据不同的编译器,结果会是这样的:
test4.cpp:10:21: error: aggregate ‘TD<int> xType’ has incomplete type and cannot be defined TD<decltype(x)> xType;
test4.cpp:11:21: error: aggregate ‘TD<const int *> yType’ has incomplete type and cannot be defined TD<decltype(y)> yType;
因此,我们知道x的类型是int, y的类型是const int*
如前所述,typeid().name()可能返回一个错误的名称。在GCC(和其他一些编译器)中,你可以使用以下代码来解决它:
#include <cxxabi.h>
#include <iostream>
#include <typeinfo>
#include <cstdlib>
namespace some_namespace { namespace another_namespace {
class my_class { };
} }
int main() {
typedef some_namespace::another_namespace::my_class my_type;
// mangled
std::cout << typeid(my_type).name() << std::endl;
// unmangled
int status = 0;
char* demangled = abi::__cxa_demangle(typeid(my_type).name(), 0, 0, &status);
switch (status) {
case -1: {
// could not allocate memory
std::cout << "Could not allocate memory" << std::endl;
return -1;
} break;
case -2: {
// invalid name under the C++ ABI mangling rules
std::cout << "Invalid name" << std::endl;
return -1;
} break;
case -3: {
// invalid argument
std::cout << "Invalid argument to demangle()" << std::endl;
return -1;
} break;
}
std::cout << demangled << std::endl;
free(demangled);
return 0;
}
基于之前的一些答案,我做出了这个解决方案,它不将__PRETTY_FUNCTION__的结果存储在二进制文件中。它使用静态数组保存类型名称的字符串表示形式。
它需要c++ 23。
#include <iostream>
#include <string_view>
#include <array>
template <typename T>
constexpr auto type_name() {
auto gen = [] <class R> () constexpr -> std::string_view {
return __PRETTY_FUNCTION__;
};
constexpr std::string_view search_type = "float";
constexpr auto search_type_string = gen.template operator()<float>();
constexpr auto prefix = search_type_string.find(search_type);
constexpr auto suffix = search_type_string.size() - prefix - search_type.size();
constexpr auto str = gen.template operator()<T>();
constexpr int size = str.size() - prefix - suffix;
constexpr auto static arr = [&]<std::size_t... I>(std::index_sequence<I...>) constexpr {
return std::array<char, size>{str[prefix + I]...};
} (std::make_index_sequence<size>{});
return std::string_view(arr.data(), size);
}
#include <iostream>
#include <typeinfo>
using namespace std;
#define show_type_name(_t) \
system(("echo " + string(typeid(_t).name()) + " | c++filt -t").c_str())
int main() {
auto a = {"one", "two", "three"};
cout << "Type of a: " << typeid(a).name() << endl;
cout << "Real type of a:\n";
show_type_name(a);
for (auto s : a) {
if (string(s) == "one") {
cout << "Type of s: " << typeid(s).name() << endl;
cout << "Real type of s:\n";
show_type_name(s);
}
cout << s << endl;
}
int i = 5;
cout << "Type of i: " << typeid(i).name() << endl;
cout << "Real type of i:\n";
show_type_name(i);
return 0;
}
输出:
Type of a: St16initializer_listIPKcE
Real type of a:
std::initializer_list<char const*>
Type of s: PKc
Real type of s:
char const*
one
two
three
Type of i: i
Real type of i:
int