Alternatives to stringifying the variable name in C++11

旧街凉风 提交于 2020-03-03 07:57:21

问题


In my code, I have repeatedly this expression:

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

I am considering stringifying the variable name, like this:

#define VARNAME(Var) (#Var)

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

T foo;
do_sth_new(foo);

Is it good practice? Is there any better alternative in C++11?


回答1:


As you show it, it doesn't work since VARNAME(foo) will always be "foo" (as this is the parameter's name). You have to write do_sth_new itself as macro:

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

Only then will this:

T bar;
do_sth_new(bar);

generate "bar".

And no, there is no alternative to using the preprocessor since this is an operation on the lexical level. You'd need LISP-level modification of the AST in the language to have a better solution, which is unlikely to ever happen.




回答2:


Sadly, no. There is still no solution (not even in C++17) to this problem. There might be something once static reflection will be added to C++. But for the time being you're stuck with the macro.




回答3:


There is no real way to avoid the macro to do the stringify.

What you can do is dress it in a more c++ object-oriented way, especially if you want to do multiple different methods that take an object and its var name, and if this is a debug feature you might want to disable in production.

So I'm proposing you declare a template class DebugContextWrap, and objects of this type (or const ref) can be passed into the function as a single parameter, instead of having 2 parameters.

The one downside is that where your function code actually wants to access the actual value then you would have to perform an indirection through operator -> or data() as you do for iterators.

You could then write a macro that generates instances of DebugContextWrap - something like:

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));


来源:https://stackoverflow.com/questions/59660682/alternatives-to-stringifying-the-variable-name-in-c11

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!