例如:
int a = 12;
cout << typeof(a) << endl;
预期的输出:
int
例如:
int a = 12;
cout << typeof(a) << endl;
预期的输出:
int
当前回答
一个没有函数重载的更通用的解决方案:
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
其他回答
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; }
代码片段
非常丑陋,但如果你只想要编译时信息(例如调试):
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*>'
一个没有函数重载的更通用的解决方案:
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
复制这个答案:https://stackoverflow.com/a/56766138/11502722
我能够在c++ static_assert()中获得这一点。这里的问题是static_assert()只接受字符串字面量;Constexpr string_view将不起作用。你需要接受typename周围的额外文本,但它可以工作:
template<typename T>
constexpr void assertIfTestFailed()
{
#ifdef __clang__
static_assert(testFn<T>(), "Test failed on this used type: " __PRETTY_FUNCTION__);
#elif defined(__GNUC__)
static_assert(testFn<T>(), "Test failed on this used type: " __PRETTY_FUNCTION__);
#elif defined(_MSC_VER)
static_assert(testFn<T>(), "Test failed on this used type: " __FUNCSIG__);
#else
static_assert(testFn<T>(), "Test failed on this used type (see surrounding logged error for details).");
#endif
}
}
MSVC输出:
error C2338: Test failed on this used type: void __cdecl assertIfTestFailed<class BadType>(void)
... continued trace of where the erroring code came from ...
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 = ⁣
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