如何找出变量的类型

How to find out the type of a variable?

本文关键字:类型 变量 何找出      更新时间:2023-10-16

我想找出一个变量的类型(变量是由模板参数给出的,所以我不知道它是什么)。

#include <iostream>
#include <typeinfo>
int main() 
{
    double test;
    std::cout << typeid(test).name() << std::endl;
}

但是代码只发出:美元。/测试

d

但是我需要double。

关键是,我不知道该期待哪种类型,但我必须在必须编译的子程序中编写它。所以d是个坏主意

如果您知道必须支持的类型列表,您可以编写自己的函数来完成此操作:

template <typename T>
void printtype()
{
  if (typeid(T) == typeid(double))
    std::cout << "double";
  else if (typeid(T) == typeid(int))
    std::cout << "int";
}

注意,由于函数没有类型为T的参数,它必须始终显式地声明类型:

printtype<double>()

当然,类型可以是参数类型:

printtype<U>()

在GNU ABI中,有一个帮助程序来请求typeidname()<子>

免责声明如果不是很明显,当然 GNU ABI只支持从GNU ABI中提取名称(甚至可能不支持大量不同的版本)。

#include <cxxabi.h>
#include <stdlib.h>
#include <string>
template <typename T> std::string nameofType(const T& v)
{
    int     status;
    char   *realname = abi::__cxa_demangle(typeid(v).name(), 0, 0, &status);
    std::string name(realname? realname : "????");
    free(realname);
    return name;
}

你可以尝试使用该表达式作为参数在模板中强制错误,编译器错误消息将具有你所寻找的类型。

例如,使用GCC:
#include <map>
#include <string>
template<typename T> void ErrorType(T &t)
{
    char x[sizeof(t)==0 ? 1 : -1];
}
template<typename T> void ErrorType(const T &t)
{
    char x[sizeof(t)==0 ? 1 : -1];
}
int main()
{
    double d = 3;
    const double cd = 3;
    ErrorType(d);
    ErrorType(cd);
    ErrorType(3);
    std::map<std::string, int> x;
    ErrorType(x.begin());
}
$ g++ -c test.cpp
test.cpp: In function ‘void ErrorType(T&) [with T = double]’:
test.cpp:17:20:   instantiated from here
test.cpp:6:14: error: size of array is negative
test.cpp: In function ‘void ErrorType(const T&) [with T = double]’:
test.cpp:18:21:   instantiated from here
test.cpp:10:14: error: size of array is negative
test.cpp: In function ‘void ErrorType(const T&) [with T = int]’:
test.cpp:19:20:   instantiated from here
test.cpp:10:14: error: size of array is negative
test.cpp: In function ‘void ErrorType(const T&) [with T = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, int> >]’:
test.cpp:22:28:   instantiated from here
test.cpp:10:14: error: size of array is negative

因此倾倒的类型为doubleintstd::_Rb_tree_iterator<std::pair<const std::basic_string<char>, int> >。第一个重载是非const的,这意味着表达式是非const的左值。

需要sizeof(t)==0的技巧来使整个表达式依赖于模板参数,并将错误延迟到实例化。当然,错误本身(数组的大小为负)是没有意义的。

如果你正在使用c++ 11,你可以改进:

#include <map>
#include <string>
template<typename T> void ErrorType(T &&t)
{
    static_assert(sizeof(t)==0, "Reporting type name");
}

int main()
{
    double d = 3;
    const double cd = 3;
    ErrorType(d);
    ErrorType(cd);
    ErrorType(3);
    std::map<std::string, int> x;
    ErrorType(x.begin());
}
$ g++ -c test.cpp  -std=gnu++0x

test.cpp: In function ‘void ErrorType(T&&) [with T = double&]’:
test.cpp:15:20:   instantiated from here
test.cpp:6:9: error: static assertion failed: "Reporting type name"
test.cpp: In function ‘void ErrorType(T&&) [with T = const double&]’:
test.cpp:16:21:   instantiated from here
test.cpp:6:9: error: static assertion failed: "Reporting type name"
test.cpp: In function ‘void ErrorType(T&&) [with T = int]’:
test.cpp:17:20:   instantiated from here
test.cpp:6:9: error: static assertion failed: "Reporting type name"
test.cpp: In function ‘void ErrorType(T&&) [with T = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, int> >]’:
test.cpp:20:28:   instantiated from here
test.cpp:6:9: error: static assertion failed: "Reporting type name"

作为额外的奖励,它可以区分const的左值和右值。第一个是double的l值,第二个是const double的l值,另外两个是r值。

注意:type_info的成员名返回的字符串取决于编译器和库的具体实现。事实并非如此必须是具有典型类型名称的简单字符串,如用于产生此输出的编译器。

编译器在this函数中调用type_info::name返回的结果例如,我们的编译器生成了易于理解的名称但这不是必需的:编译器可能只是返回任何字符串。

来源:http://www.cplusplus.com/doc/tutorial/typecasting/

我的GCC产生了混乱的名字。例如,d表示double, i表示int, c表示char, St6vectorIiSaIiEE表示std::vector<int>

来自GCC的typeinfo:

/** Returns an @e implementation-defined byte string; this is not
 *  portable between compilers!  */
const char* name() const
{ return __name[0] == '*' ? __name + 1 : __name; }

——编辑——

你不能在不同的编译器中"重复地"得到这个名字。如果你想做到这一点,你必须像John gordon在他的帖子中描述的那样硬编码。