Расширение MySQL:
Поскольку он устарел, использование его делает ваш код менее надежным.
Недостаточная поддержка подготовленных операторов особенно важна, поскольку они обеспечивают более четкий, менее подверженный ошибкам метод экранирования и цитирования внешних данных, чем ручное экранирование с помощью отдельного вызова функции.
См. сравнение расширений SQL .
Макрорасширение не работает, как расширение пакета аргументов с вариативными шаблонами. То, что у вас есть, будет расширяться до:
X,Y::do();
И не
X::do(); Y::do();
Как вы надеялись. Но в C ++ 11 вы можете использовать вариативные шаблоны. Например, вы могли бы сделать то, что хотите, таким образом:
#include <iostream>
struct X { static void foo() { std::cout << "X::foo()" << std::endl; }; };
struct Y { static void foo() { std::cout << "Y::foo()" << std::endl; }; };
struct Z { static void foo() { std::cout << "Z::foo()" << std::endl; }; };
int main()
{
do_foo<X, Y, Z>();
}
Все, что вам нужно, это (относительно простая) техника:
namespace detail
{
template<typename... Ts>
struct do_foo;
template<typename T, typename... Ts>
struct do_foo<T, Ts...>
{
static void call()
{
T::foo();
do_foo<Ts...>::call();
}
};
template<typename T>
struct do_foo<T>
{
static void call()
{
T::foo();
}
};
}
template<typename... Ts>
void do_foo()
{
detail::do_foo<Ts...>::call();
}
Вот live пример .
Вы не можете сделать это напрямую, __VA_ARGS__
всегда рассматривается как единое целое, состоящее из всех параметров, разделенных запятой. Препроцессор не обеспечивает встроенный способ поиска количества параметров, их разделения или петли над ними.
Этот ответ на аналогичный вопрос показывает основное решение, используя Препроцессор: узнайте, сколько элементов в списке аргументов и передайте его макросу, который принимает это точное количество параметров.
Я бы рекомендовал не делать этого, а вместо этого использовать Andy Prowls C ++ 11 или даже реструктурировать ваш код, чтобы он вам вообще не нужен.
На самом деле вы можете частично обойти это. Вы можете напрямую и свободно извлекать каждый элемент ни __VA_ARGS__
, ни вариационные шаблоны C ++ 11. Но у вас может быть самый первый элемент. Например, предположим, что у нас есть макрос с именем OUT(...)
, и мы хотим создать std :: cout & lt; A & lt; B & lt; C ... где A, B, C - вариационные аргументы макроса. Попробуйте следующее:
#include <iostream>
#define SEPERATOR <<
#define GET_1_OF(element1, ...) element1
#define GET_2_OF(element1, ...) element1 SEPERATOR GET_1_OF(__VA_ARGS__)
#define GET_3_OF(element1, ...) element1 SEPERATOR GET_2_OF(__VA_ARGS__)
#define BAR(...) GET_3_OF(__VA_ARGS__)
int main()
{
std::cout << BAR(1,2,3,4,5);
return 0;
}
Это, конечно, не решение, которое вам нужно. Но вы можете увеличить число GET_N_OF, чтобы делать то, что вы хотите. Обратите внимание, что SEPERATOR
- <<
, так что мы можем MACRO писать 1 << 2 << 3
и так далее. Теперь у нас есть проблема в этом коде. Измените BAR(1,2,3,4,5)
на BAR(1)
. Вы увидите, что он дает ошибку. Это связано с тем, что он ожидал 3 аргумента, хотя не имеет смысла иметь больше аргументов (потому что это переменный), у нас есть дополнительные SEPERATOR
. Поэтому для решения этой проблемы вместо использования BAR(...)
используйте GET_N_OF(...)
(поскольку вы знаете количество аргументов):
#include <iostream>
#define SEPERATOR <<
#define GET_1_OF(element1, ...) element1
#define GET_2_OF(element1, ...) element1 SEPERATOR GET_1_OF(__VA_ARGS__)
#define GET_3_OF(element1, ...) element1 SEPERATOR GET_2_OF(__VA_ARGS__)
#define GET_4_OF(element1, ...) element1 SEPERATOR GET_3_OF(__VA_ARGS__)
#define GET_5_OF(element1, ...) element1 SEPERATOR GET_4_OF(__VA_ARGS__)
int main()
{
std::cout << GET_5_OF(1,2,3,4,5);
std::cout << GET_1_OF(1);
return 0;
}
Обратите внимание, что если вы не знаете, что делаете, не использовать MACROs вообще! Мой ответ состоял в том, чтобы поделиться интересным кодом MACRO, который может быть полезен для вас. Я всегда препятствую использованию МАКРО до тех пор, пока они не станут чрезвычайно необходимыми.