C ++ макрос и шаблоны - PullRequest
       4

C ++ макрос и шаблоны

5 голосов
/ 19 февраля 2010

Есть ли способ пройти

std::map<std::string, float>

как аргумент макроса?

(проблема в том, что "," используется макросом для разделения

std::map<std::string

и

float> 

как отдельные аргументы. Я хотел бы избежать этого.

Ответы [ 6 ]

7 голосов
/ 19 февраля 2010

Нет, нет способа сделать это, кроме использования typedef.BOOST_FOREACH, например, страдает той же проблемой.

6 голосов
/ 19 февраля 2010

Попытайтесь использовать шаблон вместо макроса.

Скотт Мейерс: Эффективный C ++ Пункт 2: Предпочитайте, чтобы константы, перечисления и встраивания были # определены

5 голосов
/ 19 февраля 2010

Да, есть способ, но он косвенный.

Как вы сказали, макрос довольно тупой в своей интерпретации. Однако он все еще признает круглые скобки.

Пример: BOOST_MPL_ASSERT((boost::is_same<int,int>))

Он работает с использованием другого уровня скобок, таким образом формируя Tuple (с точки зрения макроса).

Если вы используете библиотеку Boost.Preprocessor , вы можете легко "развернуть" Tuple, чтобы получить его содержимое без повреждений. К сожалению, вы должны знать размер исходного кортежа, поэтому вам нужен дополнительный параметр

#define MY_MACRO(Size, TemplatedType, Name)\
  BOOST_PP_TUPLE_REM(Size)(TemplatedType) Name

И в действии:

MY_MACRO(2, (std::map<int,std::string>), idToName);
    // expands to 'std::map<int,std::string> idToName'
idToName[1] = "Smith";

Итак, да, это возможно, но макрос должен быть специально настроен для его обработки.

2 голосов
/ 19 февраля 2010

Один из обходных путей - «спрятать» запятую внутри другого макроса

#define ARGUMENT std::map<std::string, float> 
YOUR_MACRO(ARGUMENT)
#undef ARGUMENT

Однако, если YOUR_MACRO самому потребуется распространить его на другой уровень вниз в другой макрос, он столкнется с той же проблемой.

0 голосов
/ 07 апреля 2011

Да, до тех пор, пока вы можете расположить его так, чтобы std::map<std::string, float> был вашим последним или единственным параметром. Просто используйте __VA_ARGS__, например:

#define MAKE_A_NEW_ONE_OF_THESE(a, ...) __VA_ARGS__ *a = new __VA_ARGS__

MAKE_A_NEW_ONE_OF_THESE(pMyMap, std::map<std::string, float>);
0 голосов
/ 19 февраля 2010

У меня было нечто похожее несколько месяцев назад, если вы используете макросы и у вас есть параметры, которые содержат запятые (','), вам нужно заключить их в лишние скобки, например:

#define DEF(ret,conv,name,args) typedef ret (conv * name)(args)

//usage
DEF(void,__cdecl,Foo,(int a1, string a2)); 

этот метод может конфликтовать с некоторыми вещами / быть недопустимым в некоторых случаях, например, в этом примере (он может стать недопустимым приведением в стиле c):

#define MY_VAR(type,name) type name

//usage
MY_VAR((std::map<std::string, float>),Map);

Существует один способ решения этой проблемы, но он требует, чтобы ваш компилятор поддерживал переменные макросы ( GCC | MSVC ):

#define _W(...) __VA_ARGS__
#define VAR(x,y) x y

VAR(_W(std::map<std::string, float>),Map);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...