【问题标题】:C++ template black magicC++ 模板黑魔法
【发布时间】:2010-02-16 04:17:29
【问题描述】:

这只需要在 g++ 中工作。

我想要一个函数

template<typename T> std::string magic();

这样:

Class Foo{}; magic<Foo>(); // returns "Foo";
Class Bar{}; magic<Bar>(); // returns "Bar";

我不希望通过专业化来完成此操作(即必须为每种类型定义魔法。我希望在这里拉一些宏/模板黑魔法。有人知道怎么做吗?)

谢谢!

【问题讨论】:

  • 现在哪一部分是必要的,哪一部分是你写的,因为你认为它是必要的。 Foo类重要吗?给我们一个更现实的用例。
  • 这是对某种简单的静态反射机制的相当明显的要求,它不会带来 RTTI 的全部范围。
  • 我想要一个可以传递任何类型的函数,它会为我返回类型的名称。
  • C++ 中,您可能正在寻找模板黑魔法。如果是这样,Modern C++ Design 会很有帮助。

标签: c++ templates


【解决方案1】:

要将类型(或其他标识符)转换为字符串,您需要一个宏,但宏无法检查其参数是否为有效类型。要添加类型检查,可以将模板函数添加到宏中:​​

template<typename T>
std::string magic_impl(const char *name) { return name; }

#define more_magic(a) magic_impl<a>(#a)
#define magic(a) more_magic(a)

这里magic(int) 给出了字符串"int"magic(Foo) 给出了一个"'Foo' is not declared"如果没有这样的类的话。

【讨论】:

  • 在这里给出的所有答案中,我最喜欢这个答案,因为 a) 它会进行类型检查 b) 结果是类名,而不是任何可能依赖于编译器的损坏形式。
  • more_magic 的存在只是为了检查名为“a”的类型是否已声明并在范围内。没有它,我可以调用 magic(%%%%) 并让调用成功,即使 %%%% 不可能是一个类型的合法名称。
【解决方案2】:

先试试typeid(Foo).name()。解析你认为合适的;将取决于实现(但简单地返回一个字符串是可移植的)。

【讨论】:

  • 根据需要进行解析,例如:char *n = typeid(Foo).name(); while ( *n &amp;&amp; *n &lt; 'A' ) ++ n;
【解决方案3】:

宏上的字符串化操作符可能就是你要找的:

#define MAGICCLASSNAME(str) std::string magic(#str)
class Foo{}; MAGICCLASSNAME(foo)

【讨论】:

    【解决方案4】:

    我想出了以下内容:

    #include <iostream>
    #include <string>
    #include <typeinfo>
    
    using namespace std;
    class Foo{}; 
    class Bar{};
    
    template<typename T> 
    inline std::string magic(const T& obj)
    {
     return typeid(obj).name();
    }
    
    int main()
    {
     Foo a;
     cout << magic<Foo>(a); // returns "Foo";
    }
    

    我用 g++ 对此进行了测试,效果很好。

    我也是从this SO answer得到的。

    【讨论】:

      猜你喜欢
      • 2014-05-09
      • 1970-01-01
      • 1970-01-01
      • 2021-06-12
      • 1970-01-01
      • 2016-12-05
      • 2011-07-16
      • 2020-07-01
      • 1970-01-01
      相关资源
      最近更新 更多