Использование запятых внутри макроса без круглых скобок: как смешать и сопоставить шаблон? - PullRequest
8 голосов
/ 23 февраля 2012

Рассмотрим простой макрос:

#define ECHO(x) x

ECHO(foo(1, 2))

Это дает точный ожидаемый результат:

foo(1, 2)

Вышеприведенный пример работает, потому что круглые скобки рядом с вызовом функции распознаютсяпрепроцессор.

Теперь рассмотрим, что произойдет, если я использую шаблон вместо вызова функции:

ECHO(template<int, bool>)

Это вызывает ошибку, поскольку препроцессор интерпретирует template<int и bool> какдва отдельных аргумента к макросу.Препроцессор не распознает <> для области видимости!

Есть ли способ использовать такой шаблон в макросе?

Ответы [ 3 ]

11 голосов
/ 23 февраля 2012
#define COMMA ,
ECHO(template<int COMMA bool>)

Немного больно, но это работает.

FWIW, если синтаксис для аргумента допускает () s, вам не требуется подстановка, например,

ECHO((a, b))

будет работать для макроса с одним аргументом, но это работает не во всех случаях (включая ваш).

5 голосов
/ 21 августа 2013

Может помочь вариационный макрос:

#define ECHO(x...) x

ECHO(foo(1, 2))
ECHO(template<int, bool>)
1 голос
/ 26 февраля 2012

, если вы разрешите использование Cog в вашем проекте, ваш код станет более читабельным:

/*[[[cog
# definitions ----
import cog

def AddDeclaration( templateArg , restOfDeclaration ):
    cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration))

# generation ---
types = ['bool' , 'std::string']
names = ['Foo' , 'Bar']
for index in range(len(names)):
    AddDeclaration( 'template<int, %s>' % types[index] , names[index])
]]]*/
//[[[end]]]

После запуска cog над этим файлом вы получите:

/*[[[cog
# definitions ----
import cog

def AddDeclaration( templateArg , restOfDeclaration ):
    cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration))

# generation ---
types = ['bool' , 'std::string']
names = ['Foo' , 'Bar']
for index in range(len(names)):
    AddDeclaration( 'template<int, %s>' % types[index] , names[index])
]]]*/
template<int, bool> struct Foo; <---------------- generated by Cog!!
template<int, std::string> struct Bar;
//[[[end]]]

Вы даже можете переместить свои определения в отдельные файлы .py, и раздел cog будет выглядеть так:


declarations.py

import cog

def AddDeclaration( templateArg , restOfDeclaration ):
    cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration))

my.h

/*[[[cog
# definitions ----
import declarations
# generation ---
types = ['bool' , 'std::string']
names = ['Foo' , 'Bar']
for index in range(len(names)):
    AddDeclaration( 'template<int, %s>' % types[index] , names[index])
]]]*/
template<int, bool> struct Foo;
template<int, std::string> struct Bar;
//[[[end]]]

главное преимущество использования cog заключается в том, что вы получаете полный контроль над генерацией кода, полностью избегая нечитаемых беспорядков, используя препроцессор boost или тому подобное.

основным недостатком является то, что вы добавляете новую зависимость от инструмента в свой проект, также, поскольку вам нужно обернуть его использование в комментариях маркерами секции cog, это может быть на самом деле хуже, чем писать код вручную для небольших случаев использования. Это действительно окупается, когда вам нужно объявить большое число или много неизбежного шаблонного кода

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