For example, suppose I make a class like below:
template <unsigned int INPUT_SIZE>
class A{
public:
int operator()(int input, ...){ // get INPUT_SIZE-many inputs
// return sum;
}
};
I want to get input as many as INPUT_SIZE, not more or less. How can I achieve that?
Also, I am using c++11, but if there is a better way in c++14 or above, I would also like to know.
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
and this is a version that allows you to compute the sum of the parameters:
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);
The trick is to use a parameter pack with length N
so that we can use it to expand as N
times a specific type into the parameter list of A_impl::operator()
.
A parameter pack can expand into N
repetition of the pattern that (usually) precede ...
Consider a function like:
template<class... T>
void foo(T...);
T...
indicate in simple terms that it can be replaced by successive types into the parameter list of foo
, one possible expansion could be foo(int, int, double, char)
, also notice that what preside ...
is an identifier that comes from class... T
.
Returning to the code, we need to generate a parameter pack, we did that through std::make_index_sequence<N>
, that generate the sequence 0..(N-1)
which is captured by std::size_t... Is
, then we use this pack to expand the pattern always_t<T, Is>
that is just an alias to T=int
, this end up repeating T=int
as many times as elements Is
contains.
Note: ellipsis parameter ...
is not the same as parameter pack.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With