Альтернативы строковому названию переменной в C ++ 11 - PullRequest
1 голос
/ 09 января 2020

В моем коде я неоднократно использовал это выражение:

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?

Ответы [ 3 ]

4 голосов
/ 09 января 2020

Как вы показываете, это не работает, так как 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 на языке, чтобы найти лучшее решение, которое вряд ли когда-либо произойдет.

0 голосов
/ 09 января 2020

Нет реального способа избежать макроса для выполнения stringify.

То, что вы можете сделать, это одеть его более объектно-ориентированным способом на c ++, особенно если вы хотите использовать несколько различных методов, которые принимают объект и его имя переменной, и если это функция отладки, которую вы, возможно, захотите отключить в рабочей среде.

Поэтому я предлагаю вам объявить класс шаблона 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));
0 голосов
/ 09 января 2020

К сожалению, нет. До сих пор нет решения (даже в C ++ 17) этой проблемы. Там может быть что-то, когда stati c отражение будет добавлено в C ++. Но пока вы застряли с макросом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...