在 C++11 中字符串化变量名的替代方法

Alternatives to stringifying the variable name in C++11

在我的代码中,我重复了这个表达式:

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++17 中也没有)。一旦将静态反射添加到 C++ 中,可能会有一些东西。但是暂时你被宏困住了。

如您所示,它不起作用,因为 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 级修改以获得更好的解决方案,这不太可能发生。

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

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

所以我建议你声明一个模板 class 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));