例如:

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

预期的输出:

int

当前回答

另一个@康桓瑋的答案(最初),对前缀和后缀细节做了较少的假设,并受到@ val的答案的启发-但没有污染全局名称空间;无条件的:没有任何条件的;希望更容易阅读。

流行的编译器提供了带有当前函数签名的宏。现在,函数是可模板化的;因此签名包含模板参数。因此,基本的方法是:给定一个类型,在函数中使用该类型作为模板参数。

不幸的是,类型名称被包装在描述函数的文本中,这在不同的编译器中是不同的。例如,在GCC中,template <typename T> int foo()具有double类型的签名是:int foo() [T = double]。

那么,如何消除包装器文本呢?@HowardHinnant的解决方案是最简短和最“直接”的:只需使用每个编译器的魔法数字来删除前缀和后缀。但显然,这是非常脆弱的;没有人喜欢在代码中加入神奇的数字。然而,事实证明,给定具有已知名称的类型的宏值,您可以确定构成包装的前缀和后缀。

#include <string_view>

template <typename T> constexpr std::string_view type_name();

template <>
constexpr std::string_view type_name<void>()
{ return "void"; }

namespace detail {

using type_name_prober = void;

template <typename T>
constexpr std::string_view wrapped_type_name() 
{
#ifdef __clang__
    return __PRETTY_FUNCTION__;
#elif defined(__GNUC__)
    return __PRETTY_FUNCTION__;
#elif defined(_MSC_VER)
    return __FUNCSIG__;
#else
#error "Unsupported compiler"
#endif
}

constexpr std::size_t wrapped_type_name_prefix_length() { 
    return wrapped_type_name<type_name_prober>().find(type_name<type_name_prober>()); 
}

constexpr std::size_t wrapped_type_name_suffix_length() { 
    return wrapped_type_name<type_name_prober>().length() 
        - wrapped_type_name_prefix_length() 
        - type_name<type_name_prober>().length();
}

} // namespace detail

template <typename T>
constexpr std::string_view type_name() {
    constexpr auto wrapped_name = detail::wrapped_type_name<T>();
    constexpr auto prefix_length = detail::wrapped_type_name_prefix_length();
    constexpr auto suffix_length = detail::wrapped_type_name_suffix_length();
    constexpr auto type_name_length = wrapped_name.length() - prefix_length - suffix_length;
    return wrapped_name.substr(prefix_length, type_name_length);
}

可以在GodBolt上看到。这应该与MSVC工作以及。

其他回答

非常丑陋,但如果你只想要编译时信息(例如调试):

auto testVar = std::make_tuple(1, 1.0, "abc");
decltype(testVar)::foo= 1;

返回:

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

你可以上特质课。喜欢的东西:

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

DECLARE_TYPE_NAME定义的存在是为了让您更容易地为所有需要的类型声明这个trait类。

这可能比涉及typeid的解决方案更有用,因为您可以控制输出。例如,在我的编译器上使用typeid For long long会给出“x”。

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

Try:

#include <typeinfo>

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

您可能必须在编译器选项中激活RTTI才能使其工作。此外,它的输出取决于编译器。它可能是一个原始类型名称或名称混乱符号或介于两者之间的任何东西。

涉及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;
}