【问题标题】:C++ Simple Reflection without Macros: Print Variable Name and Its Value没有宏的 C++ 简单反射:打印变量名称及其值
【发布时间】:2011-07-27 19:18:04
【问题描述】:

在 C++ 中是否有一种非宏方式来打印带有其值的变量名。下面是宏方式:

#define SHOW(a) std::cout << #a << ": " << (a) << std::endl

PS:我用的是Linux,不需要跨平台解决方案

【问题讨论】:

  • 为什么不需要宏?你想在运行时做吗?
  • @balki:这有什么关系?
  • @baiki,不,不是运行时,但由于名称冲突和缺乏重载功能,我确实想避免在这种情况下(以及一般情况下)使用宏。

标签: c++ reflection macros


【解决方案1】:

不,C++ 不支持反射,这样做的唯一方法(据我所知)是使用宏。

【讨论】:

  • 顺便说一下,我很清楚 C++ 本身并不支持反射,但是,我认为可能有一些我不知道的非跨平台的强大解决方案。
  • @Lex:我意识到了;这就是为什么我特别提到没有宏是不可能的(你唯一的限制)。
  • @AlanTuring 在其他语言中的反射可能在某种程度上依赖于宏。 Python 本身就是一个宏。用另一个名字来称呼它,但解释层或中间编译授予类似于宏的属性。
【解决方案2】:

您可以使用动态符号,但它只能在使用 -rdynamic 标志编译的共享库或可执行文件中工作。它只会识别具有默认动态可见性的全局变量。

#include <dlfcn.h>
#include <iostream>

int NameMe = 42;

const char *GetName(const void *ptr)
{
    Dl_info info;
    if (dladdr(ptr, &info))
        return info.dli_sname;
    else
        return NULL;
}

    template<typename T>
void Dump(const T &t)
{
    const char *name = GetName(&t);
    if (name)
        std::cout << name;
    else
        std::cout << "<unknown>";
    std::cout << ": " << t << std::endl;
}
int main()
{
    int NoName = 33;
    Dump(NameMe);
    Dump(NoName);
    return 0;
}

$ g++ dump.cpp -ldl -rdynamic
$ ./a.out
NameMe: 42
<unknown>: 33

【讨论】:

    【解决方案3】:

    没办法。

    没有宏,你必须这样做:

    std::cout <<"a : " << a << std::endl; 
    

    别无他法。

    【讨论】:

      【解决方案4】:

      如果您可以让您的所有类都派生自一个共同的祖先,那么您可以提供一个虚拟函数来实现这一点。我没有尝试过这个模板,它可能不起作用 - 一些反馈将不胜感激。

      struct Reflector
      {
          virtual void Show() = 0;
      };
      template<class a, char name[]>
      struct ReflectorImpl : public Reflector
      {
          virtual void Show()
          {
              std::cout << name << ": " << *this << std::endl;
          }
      };
      
      class MyClass: public ReflectorImpl<MyClass, "MyClass">
      {
      };
      

      【讨论】:

      • 我不知道 *this 的 cout 是否可以在没有在类上定义 operator&lt;&lt; 的情况下工作。我会在基类中实现Show() 并强制(通过基类中的纯抽象方法)子类来定义operator&lt;&lt; 或某种ToString 方法。
      【解决方案5】:

      是的;在 C++17 中,您可以使用 PFR(在 C++17 模式下)来获得非平凡级别的非宏观反射。有反映枚举的“字符串值”的相关机制。

      1. https://github.com/apolukhin/magic_get;
      2. 还有https://github.com/Neargye/magic_enum

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-12
        • 2011-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多