【问题标题】:Is it possible to get a string that would containing namespace and class name at compile time?是否有可能在编译时获得一个包含命名空间和类名的字符串?
【发布时间】:2013-12-02 10:25:39
【问题描述】:

我想知道如何定义一个宏,该宏将针对给定的类名以如下格式输出其命名空间和类名:“Namespace.SubNamespace.ClassName”?

所以写这样的东西:

// MyClass.h
#include <string>

namespace NS {
 namespace SNS {
  class MyClass {
    static std::string str;
  };
 }
}

//MyClass.cpp
#include <MyClass.h>
using namespace std;
string NS::SNS::MyClass::str = SUPER_MACRO(/*params if needed yet none would be prefered*/);

我想让 str 成为“NS.SNS.MyClass”。如果可能的话,我希望该宏具有尽可能多的参数(意味着一个或没有)。

另外,我想知道是否可以使用具有以下内容的模板来完成这样的事情:

string NS::SNS::MyClass::str = GetTypeNameFormater<NS::SNS::MyClass>();

如何做这样的事情(使用 boost、stl 并且手头只有 C++03)?

【问题讨论】:

  • 显然不可能是宏。命名空间需要解析,预处理器(处理宏)在解析之前运行。 __func__ 不是一个真正的宏,尽管它看起来很像。

标签: c++ class boost c++03


【解决方案1】:

没有标准的方法来做到这一点。提供范围信息的唯一标准宏是 C99 宏 __func__。

您可以做的是通过std::typeinfo 获取符号的名称,然后将其放入编译器特定的解构API,然后解析出命名空间。

http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html 给出了如何做到这一点的例子。这应该适用于 clang 和 OS X。

或者,您可以编写一组宏来定义命名空间和相应的静态字符串,然后从那里将您的字符串组合在一起。

这两种选择都不会特别漂亮。

【讨论】:

  • -1 std::type_info::name 不需要包含命名空间。实际上,它不需要满足任何限制,并且始终为任何类型返回X 的实现是合规的。
  • @IInspectable 这就是我提到编译器特定 API 的原因。我完全知道没有直接的、符合标准的方法来做到这一点,但你可以在特定的编译器上做到这一点。这比没有要好得多,并且至少可以在两个主要编译器上工作。
【解决方案2】:

这不是一种编译时方法,但它可能会给你想要的东西。

你可以试试这样的:

nm ./a.out | grep "ZN" | c++filt

埋在我看到的输出中:

NS::SNS::MyClass::str

你也可以使用demangle.h,虽然我不确定你是如何获得错误名称的(typeid 并没有给我太多信息。)

您也可以考虑使用Boost Reflect、Boost Typetraits、Reflex 或 clang。您也许可以使用 clang 的 API 进行某种反射。

【讨论】:

    猜你喜欢
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 2013-10-03
    • 1970-01-01
    • 2016-01-17
    相关资源
    最近更新 更多