例如:
int a = 12;
cout << typeof(a) << endl;
预期的输出:
int
例如:
int a = 12;
cout << typeof(a) << endl;
预期的输出:
int
当前回答
在c++ 11中,我们有decltype。在标准c++中,没有办法显示使用decltype声明的变量的确切类型。我们可以使用boost typeindex,即type_id_with_cvr (cvr代表const, volatile, reference)来打印如下所示的类型。
#include <iostream>
#include <boost/type_index.hpp>
using namespace std;
using boost::typeindex::type_id_with_cvr;
int main() {
int i = 0;
const int ci = 0;
cout << "decltype(i) is " << type_id_with_cvr<decltype(i)>().pretty_name() << '\n';
cout << "decltype((i)) is " << type_id_with_cvr<decltype((i))>().pretty_name() << '\n';
cout << "decltype(ci) is " << type_id_with_cvr<decltype(ci)>().pretty_name() << '\n';
cout << "decltype((ci)) is " << type_id_with_cvr<decltype((ci))>().pretty_name() << '\n';
cout << "decltype(std::move(i)) is " << type_id_with_cvr<decltype(std::move(i))>().pretty_name() << '\n';
cout << "decltype(std::static_cast<int&&>(i)) is " << type_id_with_cvr<decltype(static_cast<int&&>(i))>().pretty_name() << '\n';
return 0;
}
其他回答
复制这个答案:https://stackoverflow.com/a/56766138/11502722
我能够在c++ static_assert()中获得这一点。这里的问题是static_assert()只接受字符串字面量;Constexpr string_view将不起作用。你需要接受typename周围的额外文本,但它可以工作:
template<typename T>
constexpr void assertIfTestFailed()
{
#ifdef __clang__
static_assert(testFn<T>(), "Test failed on this used type: " __PRETTY_FUNCTION__);
#elif defined(__GNUC__)
static_assert(testFn<T>(), "Test failed on this used type: " __PRETTY_FUNCTION__);
#elif defined(_MSC_VER)
static_assert(testFn<T>(), "Test failed on this used type: " __FUNCSIG__);
#else
static_assert(testFn<T>(), "Test failed on this used type (see surrounding logged error for details).");
#endif
}
}
MSVC输出:
error C2338: Test failed on this used type: void __cdecl assertIfTestFailed<class BadType>(void)
... continued trace of where the erroring code came from ...
根据Howard的解决方案,如果你不喜欢神奇的数字,我认为这是一种很好的表示方式,看起来很直观:
#include <string_view>
template <typename T>
constexpr auto type_name() {
std::string_view name, prefix, suffix;
#ifdef __clang__
name = __PRETTY_FUNCTION__;
prefix = "auto type_name() [T = ";
suffix = "]";
#elif defined(__GNUC__)
name = __PRETTY_FUNCTION__;
prefix = "constexpr auto type_name() [with T = ";
suffix = "]";
#elif defined(_MSC_VER)
name = __FUNCSIG__;
prefix = "auto __cdecl type_name<";
suffix = ">(void)";
#endif
name.remove_prefix(prefix.size());
name.remove_suffix(suffix.size());
return name;
}
演示。
#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
我喜欢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*"; }
如前所述,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;
}