【问题标题】:Alternatives to stringifying the variable name in C++11在 C++11 中对变量名进行字符串化的替代方法
【发布时间】:2020-01-09 09:20:03
【问题描述】:

在我的代码中,我多次重复这样的表达:

T foo;
do_sth(foo, "foo");

我正在考虑对变量名进行字符串化,如下所示:

#define VARNAME(Var) (#Var)

void do_sth_new(T foo) { do_sth(foo, VARNAME(foo)); };

T foo;
do_sth_new(foo);

这是好的做法吗? C++11 有没有更好的替代方案?

【问题讨论】:

  • 由于 c++ 标准中仍然缺少反射,没有丑陋的宏就没有机会让它工作。所以是的,这是当前的标准解决方案,但不是“好”:-)

标签: c++ c++11 macros


【解决方案1】:

正如您所展示的,它不起作用,因为VARNAME(foo) 将始终为"foo"(因为这是参数的名称)。您必须将do_sth_new 本身写为宏:

#define do_sth_new(_foo) \
  do { do_sth(_foo, #_foo); } while (false)

只有这样:

T bar;
do_sth_new(bar);

生成"bar"

不,除了使用预处理器之外别无选择,因为这是词法级别的操作。您需要对语言中的 AST 进行 LISP 级别的修改才能获得更好的解决方案,这不太可能发生。

【讨论】:

    【解决方案2】:

    很遗憾,没有。这个问题仍然没有解决方案(甚至在 C++17 中也没有)。一旦将静态反射添加到 C++ 中,可能会有一些东西。但暂时你还停留在宏上。

    【讨论】:

      【解决方案3】:

      没有真正的方法可以避免使用宏来进行字符串化。

      你可以做的是以更面向 C++ 的方式来装饰它,特别是如果你想要执行多个不同的方法来获取一个对象及其 var 名称,并且如果这是一个调试功能,你可能希望在生产。

      所以我建议你声明一个模板类 DebugContextWrap,并且这种类型的对象(或 const ref)可以作为单个参数传递给函数,而不是有 2 个参数。

      一个缺点是,如果您的函数代码实际上想要访问实际值,那么您必须像对迭代器一样通过 operator ->data() 执行间接寻址。

      然后您可以编写一个生成 DebugContextWrap 实例的宏 - 类似于:

      template class FooType
      class DebugContextWrap
      {
        FooType& fooVal;
        const char* debugName;
        const char* debug__FILE__val;
        const int   debug__LINE__val;
      public:
        DebugContextWrap(FooType& fooVal, 
          const char* debugName, const char* debug__FILE__val, const int debug__LINE__val)
        { ... }
        DebugContextWrap(FooType& fooVal) // implicit when caller doesn't use DEBUG_WRAP
        { ... } 
        FooType* operator ->()const
        { return &foo; }
        FooType& operator *()const
        { return foo; }
        FooType& Data()const
        { return foo; }
        const char* DebugName()const
        { return debugName; }
      
      };
      
      #define DEBUG_WRAP(foo) \
        DebugContextWrap<decltype foo>(foo, #foo, __FILE__, __LINE__)
      
      void do_sth(const DebugContextWrap<FooType>& foo);
      
      do_sth(DEBUG_WRAP(foovar));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-19
        • 1970-01-01
        • 1970-01-01
        • 2018-11-09
        • 2022-11-03
        • 2020-07-10
        • 2020-03-30
        • 2017-06-21
        相关资源
        最近更新 更多