例如:
int a = 12;
cout << typeof(a) << endl;
预期的输出:
int
例如:
int a = 12;
cout << typeof(a) << endl;
预期的输出:
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*"; }
其他回答
#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
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; }
代码片段
根据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>
int main()
{
int a = 2; // Declare type "int"
std::string b = "Hi"; // Declare type "string"
long double c = 3438; // Declare type "long double"
if(typeid(a) == typeid(int))
{
std::cout<<"int\n";
}
if(typeid(b) == typeid(std::string))
{
std::cout<<"string\n";
}
if(typeid(c) == typeid(long double))
{
std::cout<<"long double";
}
return 0;
}
我相信你想要整个单词(而不是只打印int的缩写形式(即I),你想要int),这就是为什么我做了if。
对于一些变量(字符串,long double等…)比较它们的简写形式不会输出预期的结果),您需要将应用typeid操作符的结果与特定类型的typeid进行比较。
从cppreference:
返回一个实现定义的以空结束的字符串,包含类型的名称。不提供任何保证;特别地,返回的字符串对于多个类型是相同的,并且在同一个程序的调用之间会发生变化。
在我看来,Python在这种情况下比c++更好。Python有内置的type函数,可以直接访问变量的数据类型。
你也可以使用c++filt选项-t (type)来要求类型名:
#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;
int main() {
auto x = 1;
string my_type = typeid(x).name();
system(("echo " + my_type + " | c++filt -t").c_str());
return 0;
}
仅在linux上测试。