I am trying to create a template vector of arbitrary number of int parameters and create a function to print those parameters:
namespace ex {
template <int I, class... Ts>
constexpr decltype(auto) get(Ts&& ... ts) {
return std::get<I>(std::forward_as_tuple(ts...));
}
template<int... N>
struct vec
{
static const int size = sizeof...(N);
void print() {
print(size-1);
}
void print(const int n) {
if (n >= 0) {
print(n - 1);
std::cout << ex::get<n>(N...) << std::endl;
}
}
};
}
int main()
{
ex::vec<1, 2, 3> v;
v.print();
}
And I got the following errors:
error C2672: 'ex::get': no matching overloaded function found
error C2975: 'I': invalid template argument for 'ex::get', expected compile-time constant expression
Can anyone please explain that am I missing and how to achieve the behaviour I expect?
Thanks in advance.
If you have access to C++17, you can benefit from fold expressions:
template<int... N>
struct vec {
void print() {
((std::cout << N << std::endl), ...);
}
};
Before C++17, you can use dummy array initialization trick:
template<int... N>
struct vec {
void print() {
int dummy[]{0, ((std::cout << N << std::endl), 0)...};
(void)dummy;
}
};
The first zero is there to handle empty N...
packs. The second zero is a part of a comma operator expression. The order of evaluation of arguments in a braced list is fixed by their order in that list [dcl.init.list/4].
But what if I want to operate on the individual parameter, for instance, I want to add
operator+
which adds 2 vectors. For instance addingvec<1,2,3> v1
andvec<4,5> v2
will result avec<5,7,3> v3
?
If packs can have different sizes, some tricks are needed. For example:
template<std::size_t... S, int... N, int... M>
auto add_impl(vec<N...>, vec<M...>, std::index_sequence<S...>)
{
constexpr int is1[sizeof...(S)]{N...};
constexpr int is2[sizeof...(S)]{M...};
return vec<(is1[S] + is2[S])...>{};
}
template<int... N, int... M>
auto operator+(vec<N...> v1, vec<M...> v2) {
constexpr auto size = std::max(sizeof...(N), sizeof...(M));
return add_impl(v1, v2, std::make_index_sequence<size>{});
}