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

Есть ли способ передать

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

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

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

std::map<std::string

и

float> 

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

5
задан James 19 February 2010 в 09:31
поделиться

5 ответов

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

7
ответ дан 18 December 2019 в 07:54
поделиться

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

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

6
ответ дан 18 December 2019 в 07:54
поделиться

Да, есть способ, но он непрямой.

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

Пример: BOOST_MPL_ASSERT((boost::is_same))

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

Если вы используете библиотеку 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";

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

5
ответ дан 18 December 2019 в 07:54
поделиться

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

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

Однако, если ВАШ_МАКРО сам должен передать его на другой уровень ниже в другой макрос, он столкнется с той же проблемой.

2
ответ дан 18 December 2019 в 07:54
поделиться

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

#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);
0
ответ дан 18 December 2019 в 07:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: