例如:

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

预期的输出:

int

当前回答

不要忘记包含<typeinfo>

我相信您所指的是运行时类型标识。你可以通过做来达到以上目的。

#include <iostream>
#include <typeinfo>

using namespace std;

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

其他回答

如前所述,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;

}

涉及RTTI (typeid)的其他答案可能是您想要的,只要:

您可以承担内存开销(对于某些编译器,这可能相当大) 编译器返回的类名很有用

另一种选择(类似于Greg Hewgill的答案)是建立一个特征的编译时表。

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";
};

注意,如果你将声明包装在宏中,你将在声明带有多个参数的模板类型时遇到麻烦(例如std::map),这是由于逗号的原因。

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

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

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

Howard Hinnant使用魔法数字提取类型名称。康桓瑋建议字符串前缀和后缀。但是前缀/后缀一直在变化。 使用" probe_type " type_name自动计算" probe_type "的前缀和后缀大小,以提取类型名称:

#include <string_view>
using namespace std;

namespace typeName {
 template <typename T>
  constexpr string_view wrapped_type_name () {
#ifdef __clang__
    return __PRETTY_FUNCTION__;
#elif defined(__GNUC__)
    return  __PRETTY_FUNCTION__;
#elif defined(_MSC_VER)
    return  __FUNCSIG__;
#endif
  }

  class probe_type;
  constexpr string_view probe_type_name ("typeName::probe_type");
  constexpr string_view probe_type_name_elaborated ("class typeName::probe_type");
  constexpr string_view probe_type_name_used (wrapped_type_name<probe_type> ().find (probe_type_name_elaborated) != -1 ? probe_type_name_elaborated : probe_type_name);

  constexpr size_t prefix_size () {
    return wrapped_type_name<probe_type> ().find (probe_type_name_used);
  }

  constexpr size_t suffix_size () {
    return wrapped_type_name<probe_type> ().length () - prefix_size () - probe_type_name_used.length ();
  }

  template <typename T>
  string_view type_name () {
    constexpr auto type_name = wrapped_type_name<T> ();

    return type_name.substr (prefix_size (), type_name.length () - prefix_size () - suffix_size ());
  }
}

#include <iostream>

using typeName::type_name;
using typeName::probe_type;

class test;

int main () {
  cout << type_name<class test> () << endl;

  cout << type_name<const int*&> () << endl;
  cout << type_name<unsigned int> () << endl;

  const int ic = 42;
  const int* pic = &ic;
  const int*& rpic = pic;
  cout << type_name<decltype(ic)> () << endl;
  cout << type_name<decltype(pic)> () << endl;
  cout << type_name<decltype(rpic)> () << endl;

  cout << type_name<probe_type> () << endl;
}

输出

gcc 10.2:

test
const int *&
unsigned int
const int
const int *
const int *&
typeName::probe_type

铿锵声11.0.0:

test
const int *&
unsigned int
const int
const int *
const int *&
typeName::probe_type

VS 2019版本16.7.6:

class test
const int*&
unsigned int
const int
const int*
const int*&
class typeName::probe_type

我喜欢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*"; }