如何找出变量的类型?

时间:2011-11-23 22:33:49

标签: c++ types

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

#include <iostream>
#include <typeinfo>

int main() 
{
    double test;
    std::cout << typeid(test).name() << std::endl;
}

但该守则只发出: $。/测试

d

但我需要双倍。

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

4 个答案:

答案 0 :(得分:3)

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

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>()

答案 1 :(得分:2)

在GNU ABI中,name() typeid #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; } <子>

  

免责声明如果不明显,当然 GNU ABI只支持GNU ABI中的demangling名称(可能甚至没有大不相同的版本)。   

{{1}}

答案 2 :(得分:2)

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

例如,使用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 l值。

需要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 l值和r值之间产生差异。第一个是double l值,第二个是const double l值,另外两个是r值。

答案 3 :(得分:1)

  

注意:type_info成员名返回的字符串取决于   您的编译器和库的具体实现。它不是   必须是一个简单的字符串,其典型的类型名称,如在   用于生成此输出的编译器。

     

我们的编译器在调用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; }

- 编辑 -

您无法“重复”获取编译器之间的名称。如果你想做到这一点,你必须像约翰戈登在他的帖子中描述的那样硬编码。