例如:

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

预期的输出:

int

当前回答

对于那些还在访问的人,我最近也遇到了同样的问题,并决定根据这篇文章的答案编写一个小型库。它提供了constexpr类型名称和类型索引,并且在Mac, Windows和Ubuntu上进行了测试。

库代码在这里:https://github.com/TheLartians/StaticTypeInfo

其他回答

Try:

#include <typeinfo>

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

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

不要忘记包含<typeinfo>

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

#include <iostream>
#include <typeinfo>

using namespace std;

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

根据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;
}

演示。

另一个@康桓瑋的答案(最初),对前缀和后缀细节做了较少的假设,并受到@ 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工作以及。

c++在编译时使用模板和运行时使用TypeId进行数据类型解析。

编译时解决方案。

template <std::size_t...Idxs>
constexpr auto substring_as_array(std::string_view str, std::index_sequence<Idxs...>)
{
  return std::array{str[Idxs]..., '\n'};
}

template <typename T>
constexpr auto type_name_array()
{
#if defined(__clang__)
  constexpr auto prefix   = std::string_view{"[T = "};
  constexpr auto suffix   = std::string_view{"]"};
  constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
#elif defined(__GNUC__)
  constexpr auto prefix   = std::string_view{"with T = "};
  constexpr auto suffix   = std::string_view{"]"};
  constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
#elif defined(_MSC_VER)
  constexpr auto prefix   = std::string_view{"type_name_array<"};
  constexpr auto suffix   = std::string_view{">(void)"};
  constexpr auto function = std::string_view{__FUNCSIG__};
#else
# error Unsupported compiler
#endif

  constexpr auto start = function.find(prefix) + prefix.size();
  constexpr auto end = function.rfind(suffix);

  static_assert(start < end);

  constexpr auto name = function.substr(start, (end - start));
  return substring_as_array(name, std::make_index_sequence<name.size()>{});
}

template <typename T>
struct type_name_holder {
  static inline constexpr auto value = type_name_array<T>();
};

template <typename T>
constexpr auto type_name() -> std::string_view
{
  constexpr auto& value = type_name_holder<T>::value;
  return std::string_view{value.data(), value.size()};
}

运行时的解决方案。

template <typename T>
void PrintDataType(T type)
{
    auto name = typeid(type).name();
    string cmd_str = "echo '" + string(name) + "' | c++filt -t";
    system(cmd_str.c_str());
}

主要代码

#include <iostream>
#include <map>
#include <string>
#include <typeinfo>
#include <string_view>
#include <array>   // std::array
#include <utility> // std::index_sequence
using std::string;

int main () { / /动态分辨率。 std::map<int, int> iMap; PrintDataType (iMap); //编译类型解析。 std:: cout < < type_name < std::列表< int > > () < < std:: endl; 返回0; }

代码片段