Как создать функцию variadi c, которая будет рекурсивной с данным псевдокодом в C ++? - PullRequest
1 голос
/ 02 мая 2020

Я пытаюсь создать рекурсивную шаблонную функцию variadi c, которая работает в следующем примере. Пример не показывает практичности и используется только для того, чтобы лучше понять, что я спрашиваю. Итак, в основном у меня есть функция, которая принимает бесконечное количество параметров одного типа и рекурсивно вызывает себя со всеми, кроме последних параметров. Затем, когда он, наконец, достигнет двух параметров, следующая функция выполняет функцию завершения. Я знаю, что ответ не тривиален, и мне трудно понять, что делать. Любая помощь или направление будут оценены! Спасибо.

template <typename... Ts>
void test(int& a, int& b, Ts&... ts){
    test(a, b, ... ); //all but the last parameter

    //last parameter argument is processed here

}

void test(int& a, int& b){
    //end of recursion
}

int main(int argc, char** argv){

    int a = 3;
    int b = 5;
    int c = 6;
    int d = 4;

    test(a, b, c, d);

    return 0;
}

1 Ответ

0 голосов
/ 02 мая 2020

Мы можем переслать аргументы в кортеже и уменьшить индекс:

#include <cstddef>
#include <tuple>
#include <utility>

template <std::size_t I, typename Tuple>
void test_helper(Tuple&& tuple)
{
    if constexpr (I != 0) {
        test_helper<I - 1>(std::forward<Tuple>(tuple));
    }

    // for example
    process(std::get<I>(std::forward<Tuple>(tuple)));
}

template <typename... Args>
void test(Args&&... args)
{
    test_helper<sizeof...(Args) - 1>(std::forward_as_tuple(std::forward<Args>(args)...));
}

Пример:

#include <cstddef>
#include <iostream>
#include <tuple>
#include <utility>

template <typename T>
void process(const T& arg)
{
    std::cout << arg << '\n';
}

template <std::size_t I, typename Tuple>
void test_helper(Tuple&& tuple)
{
    process(std::get<I>(std::forward<Tuple>(tuple)));

    if constexpr (I != 0) {
        test_helper<I - 1>(std::forward<Tuple>(tuple));
    }
}

template <typename... Args>
void test(Args&&... args)
{
    test_helper<sizeof...(Args) - 1>(std::forward_as_tuple(std::forward<Args>(args)...));
}

int main()
{
    test(1, '2', "3", 4.0);
}

( live demo )


А пока предпочитайте обрабатывать аргументы слева направо, что намного проще:

template <typename... Args>
void test(Args&&... args)
{
    ((void)process(std::forward<Args>(args)), ...);
}

Обработка справа налево станет проще с P1858 Обобщенное объявление пакета и его использование , который, к сожалению, еще не принят:

template <typename... Args>
void test(Args&&... args)
{
    test(std::forward<Args>(args)...[:-1]...);

    if constexpr (sizeof...(Args) != 0) {
        process(std::forward<Args>(args)...[-1]);
    }
}
...