Как использовать __VA_ARGS__ в C или CPP [дубликат]

Расширение MySQL:

  • Не находится в активной разработке
  • Официально устарела с PHP 5.5 (выпущена в июне 2013 г.).
  • Полностью удален с PHP 7.0 (выпущен в декабре 2015 года). Это означает, что с 31 декабря 2018 года он не будет существовать ни в одной поддерживаемой версии PHP. В настоящее время он получает обновления security .
  • Недостаток интерфейса OO
  • Не поддерживает: неблокирующие, асинхронные запросы Подготовленные операторы или параметризованные запросы Хранимые процедуры Несколько операторов транзакций «Новые», метод аутентификации пароля (по умолчанию в MySQL 5.6, требуется в 5.7). Все функциональные возможности в MySQL 5.1

Поскольку он устарел, использование его делает ваш код менее надежным.

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

См. сравнение расширений SQL .

3
задан Andy Prowl 4 May 2013 в 11:03
поделиться

3 ответа

Макрорасширение не работает, как расширение пакета аргументов с вариативными шаблонами. То, что у вас есть, будет расширяться до:

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 пример .

5
ответ дан Andy Prowl 28 August 2018 в 23:23
поделиться

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

Этот ответ на аналогичный вопрос показывает основное решение, используя Препроцессор: узнайте, сколько элементов в списке аргументов и передайте его макросу, который принимает это точное количество параметров.

Я бы рекомендовал не делать этого, а вместо этого использовать Andy Prowls C ++ 11 или даже реструктурировать ваш код, чтобы он вам вообще не нужен.

1
ответ дан Community 28 August 2018 в 23:23
поделиться

На самом деле вы можете частично обойти это. Вы можете напрямую и свободно извлекать каждый элемент ни __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, который может быть полезен для вас. Я всегда препятствую использованию МАКРО до тех пор, пока они не станут чрезвычайно необходимыми.

1
ответ дан Equalities of polynomials 28 August 2018 в 23:23
поделиться
Другие вопросы по тегам:

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