有没有办法获得给定数量的输入,而输入的数量是由模板在c ++中的编译时给出的?

时间:2018-12-23 04:29:31

标签: c++ templates

例如,假设我制作了一个如下所示的类:

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 :(得分:14)

Live demo 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

这是一个允许您计算参数总和的版本:

Live demo 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的{​​{3}},以便我们可以将其扩展为特定类型的N倍到A_impl::operator()的参数列表中。

参数包可以扩展为N(通常)在...之前的模式的重复


考虑如下功能:

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

T...用简单的术语表示它可以用连续的类型替换为foo的参数列表,可能的扩展名可以是foo(int, int, double, char),还请注意{{1 }}是来自...的标识符。


返回代码,我们需要生成一个参数包,我们通过class... T进行了操作,生成了std::make_index_sequence<N>捕获的序列0..(N-1),然后使用了这个包扩展模式std::size_t... Is只是always_t<T, Is>的别名,最终导致T=int重复的次数与元素T=int所包含的次数相同。

注意:省略号参数Is与参数包不同。