c++ - 在C++中,打印变量类型

在标准C++中是否可以打印变量类型,

我想要这样的东西:


int a = 12;
cout << typeof(a) << endl;

可以打印:

 
int

 

时间:

尝试以下方法:


#include <typeinfo>

// …
std::cout << typeid(a).name() << 'n';

你可能必须在编译器选项中激活RTTI才能工作,此外,输出取决于编译器。

在C++中打印变量类型。

答案是使用typeid(a).name(),其中a是变量名。

现在C++11中有decltype(x),它可以将表达式转换为类型,decltype()提供了规则集,例如,decltype(a)decltype((a))通常是不同类型的(而且,因为这些原因,为了获得良好的和可理解的原因)。

最基本的问题是:

 
typeid(a).name()

 

例如:


const int ci = 0;
std::cout << typeid(ci).name() << 'n';

对于我输出:

 
i

 

我猜测MSVC的输出:

 
int

 

标准规定了这种行为。

我推荐的内容如下:


template <typename T> std::string type_name();


const int ci = 0;
std::cout << type_name<decltype(ci)>() << 'n';

对于我的输出:

 
int const

 

C++11解决方案


#include <type_traits>
#include <typeinfo>
#ifndef _MSC_VER
# include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>

template <class T>
std::string
type_name()
{
 typedef typename std::remove_reference<T>::type TR;
 std::unique_ptr<char, void(*)(void*)> own
 (
#ifndef _MSC_VER
 abi::__cxa_demangle(typeid(TR).name(), nullptr,
 nullptr, nullptr),
#else
 nullptr,
#endif
 std::free
 );
 std::string r = own != nullptr ? own.get() : typeid(TR).name();
 if (std::is_const<TR>::value)
 r +=" const";
 if (std::is_volatile<TR>::value)
 r +=" volatile";
 if (std::is_lvalue_reference<T>::value)
 r +="&";
 else if (std::is_rvalue_reference<T>::value)
 r +="&&";
 return r;
}

我可以做到:


int& foo_lref();
int&& foo_rref();
int foo_value();

int
main()
{
 int i = 0;
 const int ci = 0;
 std::cout <<"decltype(i) is" << type_name<decltype(i)>() << 'n';
 std::cout <<"decltype((i)) is" << type_name<decltype((i))>() << 'n';
 std::cout <<"decltype(ci) is" << type_name<decltype(ci)>() << 'n';
 std::cout <<"decltype((ci)) is" << type_name<decltype((ci))>() << 'n';
 std::cout <<"decltype(static_cast<int&>(i)) is" << type_name<decltype(static_cast<int&>(i))>() << 'n';
 std::cout <<"decltype(static_cast<int&&>(i)) is" << type_name<decltype(static_cast<int&&>(i))>() << 'n';
 std::cout <<"decltype(static_cast<int>(i)) is" << type_name<decltype(static_cast<int>(i))>() << 'n';
 std::cout <<"decltype(foo_lref()) is" << type_name<decltype(foo_lref())>() << 'n';
 std::cout <<"decltype(foo_rref()) is" << type_name<decltype(foo_rref())>() << 'n';
 std::cout <<"decltype(foo_value()) is" << type_name<decltype(foo_value())>() << 'n';
}

输出是:


decltype(i) is int
decltype((i)) is int&
decltype(ci) is int const
decltype((ci)) is int const&
decltype(static_cast<int&>(i)) is int&
decltype(static_cast<int&&>(i)) is int&&
decltype(static_cast<int>(i)) is int
decltype(foo_lref()) is int&
decltype(foo_rref()) is int&&
decltype(foo_value()) is int


decltype(i) is int
decltype((i)) is int
decltype(ci) is int
decltype((ci)) is int
decltype(static_cast<int&>(i)) is int
decltype(static_cast<int&&>(i)) is int
decltype(static_cast<int>(i)) is int
decltype(foo_lref()) is int
decltype(foo_rref()) is int
decltype(foo_value()) is int

通过执行以下操作来实现上述操作。


#include <iostream>
#include <typeinfo>

using namespace std;

int main() {
 int i;
 cout << typeid(i).name();
 return 0;
}

注意,由C++的RTTI特性生成的名称是不可移植的。 例如类


MyNamespace::CMyContainer<int, test_MyNamespace::CMyObject>

将有以下名称:


// MSVC 2003:
class MyNamespace::CMyContainer[int,class test_MyNamespace::CMyObject]
// G++ 4.2:
N8MyNamespace8CMyContainerIiN13test_MyNamespace9CMyObjectEEE

你可以使用模板。


template <typename T> const char* typeof(T&) { return"unknown"; } // default
template<> const char* typeof(int&) { return"int"; }
template<> const char* typeof(float&) { return"float"; }

在上面的例子中,当类型不匹配时,它将打印"unknown"


auto testVar = std::make_tuple(1, 1.0,"abc");
static_assert(decltype(testVar)::dummy_error,"DUMP MY TYPE" );

返回:


Compilation finished with errors:
source.cpp: In function 'int main()':
source.cpp:5:19: error: 'dummy_error' is not a member of 'std::tuple<int, double, const char*>'

你可以用一个trait类,就像这样:


#include <iostream>
using namespace std;

template <typename T> class type_name {
public:
 static const char *name;
};

#define DECLARE_TYPE_NAME(x) template<> const char *type_name<x>::name = #x;
#define GET_TYPE_NAME(x) (type_name<typeof(x)>::name)

DECLARE_TYPE_NAME(int);

int main()
{
 int a = 12;
 cout << GET_TYPE_NAME(a) << endl;
}

在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;

}

其他涉及RTTI (typeid )的答案可能是你所需要的,只要:


template <typename T> struct type_as_string;

// declare your Wibble type (probably with definition of Wibble)
template <>
struct type_as_string<Wibble>
{
 static const char* const value ="Wibble";
};

要访问变量类型的名称,你需要的是


template <typename T>
const char* get_type_as_string(const T&)
{
 return type_as_string<T>::value;
}

一个没有函数重载的,更通用的解决方案:


template<typename T>
std::string TypeOf(T){
 std::string Type="unknown";
 if(std::is_same<T,int>::value) Type="int";
 if(std::is_same<T,std::string>::value) Type="String";
 if(std::is_same<T,MyClass>::value) Type="MyClass";

 return Type;}

MyClass的用户定义类,可以在这里添加更多条件。

例如:


#include <iostream>



class MyClass{};


template<typename T>
std::string TypeOf(T){
 std::string Type="unknown";
 if(std::is_same<T,int>::value) Type="int";
 if(std::is_same<T,std::string>::value) Type="String";
 if(std::is_same<T,MyClass>::value) Type="MyClass";
 return Type;}


int main(){;
 int a=0;
 std::string s="";
 MyClass my;
 std::cout<<TypeOf(a)<<std::endl;
 std::cout<<TypeOf(s)<<std::endl;
 std::cout<<TypeOf(my)<<std::endl;

 return 0;}

输出:

 
int
String
MyClass

 

...