Есть ли способ получить заданное количество входов, где номер задается шаблоном во время компиляции в C ++? - PullRequest
0 голосов
/ 23 декабря 2018

Например, предположим, что я создаю класс, как показано ниже:

template <unsigned int INPUT_SIZE>
class A{
public:
    int operator()(int input, ...){ // get INPUT_SIZE-many inputs
        // return sum;
    }
};

Я хочу получить столько же, сколько INPUT_SIZE, но не больше или меньше.Как мне этого добиться?

Кроме того, я использую c ++ 11, но если есть лучший способ в c ++ 14 или выше, я также хотел бы знать.

1 Ответ

0 голосов
/ 23 декабря 2018

Демонстрация в реальном времени 1

template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
    int operator ()(always_t<T, Is>...)
    {
        return 0;
    }
};
template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>
{ };


A<2>{}(1, 2); // fine
A<2>{}(1, 2, 3); // fail

, и это версия, которая позволяет вычислять сумму параметров:

Демонстрация в реальном времени 2

template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
    constexpr int operator ()(std::tuple<always_t<T, Is>...>&& t) {
        auto adder = [](auto... ts) {
            return (0 + ... + ts);
        };
        return std::apply(adder, std::move(t));
    }
};

template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>{
};

constexpr int sum = A<3>{}({1, 4, 5});
static_assert(sum == 10);

Хитрость заключается в использовании пакета параметров сдлина N, чтобы мы могли использовать его для расширения как N раз определенного типа в список параметров A_impl::operator().

Пакет параметров может расширяться до N повторения шаблона, который (обычно) пред ...


Рассмотрим такую ​​функцию, как:

template<class... T>
void foo(T...);

T... в простых терминах указывают, что ее можно заменить последовательными типами в списке параметров foo, одним из возможных расширений может быть foo(int, int, double, char), также обратите внимание, что председателем ... является идентификатор, который приходит из class... T.


Возвращаясь к коду, нам нужно сгенерировать параметрПакет, мы сделали это через std::make_index_sequence<N>, который генерирует последовательность 0..(N-1), которая захватывается std::size_t... Is, затем мы используем этот пакет, чтобы расширить тШаблон always_t<T, Is>, который является просто псевдонимом T=int, в конечном итоге повторяет T=int столько раз, сколько содержится в элементах Is.

Примечание: параметр многоточия ... отличается отпакет параметров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...