【问题标题】:How to convert typename T to string in c++ [duplicate]如何在c ++中将typename T转换为字符串[重复]
【发布时间】:2011-05-27 23:10:16
【问题描述】:

在使用 c++ 中的模板时,我遇到了将类型名 T 转换为字符串的问题。例如:

template <typename T>
class Matrix {
   public:
        Matrix() {
           //my_type = string type of T. i.e. if T is char. I want my_type to be "char".
        }
   string my_type;
}

如何将 T 转换为表示 T 是什么的字符串。

注意:我只是在玩,所以请不要担心什么时候可能需要这样的东西。

【问题讨论】:

标签: c++ templates


【解决方案1】:

对此没有内置机制。

typeid(T)::name() 可以提供一些信息,但标准不要求此字符串是人类可读的;只是它必须对每种类型都不同。 (例如,Microsoft Visual C++ 使用人类可读的字符串;GCC 不使用。)

不过,您可以构建自己的系统。例如,基于特征的。像这样的:

// default implementation
template <typename T>
struct TypeName
{
    static const char* Get()
    {
        return typeid(T).name();
    }
};

// a specialization for each type of those you want to support
// and don't like the string returned by typeid
template <>
struct TypeName<int>
{
    static const char* Get()
    {
        return "int";
    }
};

// usage:
const char* name = TypeName<MyType>::Get();

【讨论】:

  • 生成该专业化可以说是宏的一个案例:#define ENABLE_TYPENAME(A) template&lt;&gt; struct TypeName&lt;A&gt; { static const char *Get() { return #A; }};。然后,当我编写我的课程Foo 时,我可以做ENABLE_TYPENAME(Foo),如有必要,将其放入正确的命名空间中。
  • “每种类型都不同”不,你甚至没有这个保证
  • 请注意,GCC 给了 Itanium ABI 错位名称,可以使用 Itanium ABI 函数对其进行错位。
  • 我必须省略专业化的template &lt;&gt; 部分才能使其正常工作。 Borland C++(是的,一个 20 多年前的旧编译器)。
【解决方案2】:

对于 GCC,您必须使用一个技巧。使用cxxabi.h,我为此编写了一个小包装器:

#include <string>
#include <iostream>
#include <iomanip>
#include <typeinfo>
#include <cxxabi.h>

#define DEBUG_TYPE(x) do { typedef void(*T)x; debug_type<T>(T(), #x); } while(0)

template<typename T>
struct debug_type
{
    template<typename U>
    debug_type(void(*)(U), const std::string& p_str)
    {
        std::string str(p_str.begin() + 1, p_str.end() - 1);
        std::cout << str << " => ";
        char * name = 0;
        int status;
        name = abi::__cxa_demangle(typeid(U).name(), 0, 0, &status);
        if (name != 0) { std::cout << name << std::endl; }
        else { std::cout << typeid(U).name() << std::endl; }
        free(name);
    }
};

双括号是必需的。适用于任何类型。

现在您可以将它用于boost::mpl

DEBUG_TYPE((if_c<true, true_, false_>::type));

将打印:

if_c<true, true_, false_>::type => bool_<true>

【讨论】:

  • 这不会使它成为特定于 Itanium 64 位的处理器吗?还是可以在其他架构上使用?
  • @serup abi::__cxa_demanble 应该可以在任何架构上与 gcc 一起使用(例如,我在 ARM 上使用过它)。
【解决方案3】:

你不能,至少不能直接。将一个标记或一系列标记转换为字符串文字的唯一方法是在宏内部使用预处理器的字符串化运算符 (#)。

如果你想得到一个表示类型的字符串字面量,你必须自己写一些东西,也许通过使用宏来实例化模板并将字符串化的类型名称传递给它。

任何通用方法的一个问题是:应该为以下用途提供什么字符串:

Matrix<char> x;
typedef char MyChar;
Matrix<MyChar> y;

xy都是同一种类型,但是一个直接使用char,另一个使用typedef MyChar

【讨论】:

    【解决方案4】:

    如果类型是基本类型之一,则不可能在string 中获取类型名称。对于用户定义的类型,您可以使用typeid(my_type).name()。你还需要#include &lt;typeinfo&gt; :) more info...

    【讨论】:

      【解决方案5】:

      解决方法...

      #define Tprint(x) print<x>(#x)
      
      template<typename T>
      void print (string ltype){
      cout<<ltype<<" = "<<sizeof(T)<<endl;
      }
      

      【讨论】:

      • 请原谅我的格式不好。我在 stackover flow 中的第一篇文章。
      • 我很确定,如果你这样做 Tprint(T) 其中T 是原始问题中给出的模板参数,你会得到T = 4 或一些数字。您不会将 T 的类型写入屏幕。
      【解决方案6】:

      您可以使用C++ reflection library。所以:

      using namespace ponder;
      
      Class::declare<Matrix>();
      
      std::string const& name = classByType<Matrix>().name();
      

      一旦您获得元类信息,这也为您提供了其他选项,例如查看类成员是什么。

      【讨论】:

        【解决方案7】:
        template< typename From,typename To>
        static inline bool superConvert(const From& fromVar,To& toVar)
        {
            stringstream ss;
            ss<<fromVar;
            ss>>toVar;
            if(ss.fail())
            {
                return false;
            }
            else
            {
                From tempFrom;
                stringstream ss;
                ss<<toVar;
                ss>>tempFrom;
                if(tempFrom != fromVar)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }
        

        【讨论】:

        • 我不明白这与问题有什么关系。
        • 你可以将任何类型转换为字符串,
        • 你误解了这个问题,他试图获取模板中使用的类型的字符串名称。本质上是std::string type = "&lt;T&gt;",只是那不起作用。
        猜你喜欢
        • 2015-10-15
        • 2015-09-21
        • 2016-09-05
        • 1970-01-01
        • 1970-01-01
        • 2011-08-19
        • 1970-01-01
        • 1970-01-01
        • 2014-03-15
        相关资源
        最近更新 更多