Я хочу удалить аргумент из переменных аргументов, используя шаблонное метапрограммирование - PullRequest
4 голосов
/ 21 мая 2019

Я новичок в шаблонах метапрограммирования. Я хочу убрать аргументы из аргумента переменной в C ++. Я делаю функцию, которая будет push_back() элемент для любого типа контейнера. Это очень легко сделать в C ++ 17, но я хочу обеспечить поддержку C ++ 11. Пожалуйста, найдите код ниже push_back() реализации функции, которую я ищу. Пожалуйста, избегайте решений va_start(), va_end() c.


#include <iostream>
#include <vector>
template<class Container, class T, class... Args>
void push_back(Container& con, T tail, Args... args);

template<class T>
T get_tail(T data) {
    return data;
}

template<class T, class ...Args>
T get_tail(T& tail, Args&... args) {
    return tail;
}

template<class Container , class T,class... Args>
void push_back(Container& con, T tail,Args... args ) {
        //C++ 17 ((con.push_back(args), ...);
    con.push_back(tail);
    std::cout << (tail) << std::endl;
    T newTail = get_tail(args...);
    push_back(con,newTail,args...); 
}

template<typename T, typename... Args>
bool pair_comparer(T a, T b, Args... args) {
    return a == b && pair_comparer(args...);
}

int main()
{
    std::vector<int> v_int;
    push_back(v_int,1,2,3,4 );
  std::cout << "Hello World!\n";
    for (auto iter = v_int.begin(); iter != v_int.begin(); iter++) {
        std::cout << "=== " << *iter << " ===" << std::endl;
    }
}

Ответы [ 3 ]

2 голосов
/ 21 мая 2019

Вы уже убрали первый аргумент, когда сделали

void push_back(Container& con, T tail, Args... args ) {

tail является первым аргументом, а args - остальным, поэтому ваш рекурсивный вызов в конце просто должен сказать

pus_back(con, args...)

Нет необходимости в этом get_tail хакерстве. Затем просто перегрузите push_back, который выглядит следующим образом.

template <class Container>
void push_back(Container& con) {
  // A whole lot of nothing happens here...
}

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

1 голос
/ 21 мая 2019

Не уверен, что понимаю, что именно вам нужно, но ...

Вы уверены, что вам нужна рекурсия?

Вы можете разработать что-то похожее на C ++ 17, распаковывая variadic args..., используя инициализацию неиспользуемого массива в стиле C, следующим образом

template <typename Container, typename ... Args>
void push_back (Container & con, Args ... args ) {
   using unused = int[];

   (void)unused { 0, ((void)con.push_back(args), std::cout << args << std::endl, 0)... };
}

или просто следующим образом

template <typename Container, typename ... Args>
void push_back (Container & con, Args ... args ) {
   using unused = int[];

   (void)unused { 0, ((void)con.push_back(args), 0)... };
}

, если часть std::cout предназначена только для целей отладки.

1 голос
/ 21 мая 2019

Проблема в вашем коде в том, что вы вызываете push_back внутри себя с таким же числом аргументов.Это делает рекурсию бесконечной.Вместо этого вам нужно "лишить" один аргумент каждый раз.И, конечно, обеспечить базу рекурсии.Как это:

template<class Container>
void push_back(Container& con) {
}

template<class Container , class T,class... Args>
void push_back(Container& con, T tail, Args... args ) {
    con.push_back(tail);
    std::cout << (tail) << std::endl;
    push_back(con, args...);
}


int main()
{
    std::vector<int> v_int;
    push_back(v_int,1,2,3,4 );
    std::cout << "Hello World!\n";
    for (auto x : v_int)
        std::cout << "=== " << x << " ===" << std::endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...