Reputation: 2271
I have the following problem:
template< size_t... N_i >
class A
{
public:
// ...
void foo()
{
bar( /* 0,...,0 <- sizeof...(N_i) many */);
}
};
I want to call a function bar
and pass sizeof...(N_i)
many arguments to it which are all zeros, e.g., bar(0,0,0)
in case sizeof...(N_i) == 3
.
How can this be implemented?
Upvotes: 38
Views: 2831
Reputation: 1
You can also use the fact that if we subtract any positive integer from itself we get 0
.
template< size_t... N_i >
class A
{
public:
void foo()
{
//------vvvvvvvvv-------->expand to N_i 0's
bar( (N_i - N_i)...);
}
//for ending recursion
void bar()
{
}
//generalized version
template<typename T, typename... Types>
void bar(T t, Types... types)
{
std::cout << t << "\n";
bar(types...);
}
};
int main()
{
A<1,2,3,4,10> a;
a.foo();
}
Upvotes: 0
Reputation: 50550
Despite the undoubtedly interesting answer by @Columbo, I want to suggest another viable solution based on constexpr
'd template variables:
#include <cstddef>
template<std::size_t, std::size_t V>
constexpr std::size_t repeat_value = V;
template<std::size_t... N_i>
class A {
template<typename... Args>
void bar(Args&&...) { }
public:
void foo() {
// repeat N_i times value 0
bar(repeat_value<N_i, 0>...);
}
};
int main() {
A<0, 1, 2, 3, 4> a;
a.foo();
}
I find it easier to read at least, even if it's bad in terms of performance at compile-time.
You can easily generalize it as it follows:
template<std::size_t, typename T, T V>
constexpr T repeat_value = V;
The invokation in the specific case is this:
bar(repeat_value<N_i, int, 0>...);
Upvotes: 9
Reputation: 855
You could also use templates to simulate something similar. This is a very basic solution and will just create a list of 0s, but it could be extended to generate other sequences if that was desired.
template <size_t Unused>
struct Wrap {
static constexpr size_t value = 0;
};
template <size_t... N_i>
class A {
public:
void foo() {
bar(Wrap<N_i>::value...);
}
};
Which will just expand into a list of zeros of the same size as the N_i arguments. Admittedly, the interface is slightly different.
For a complete example, which shows the values of the elements which bar receives, see here: Live example
Upvotes: 2
Reputation: 60989
bar(((void)N_i, 0)...);
The comma operator will discard N_i
, yielding just the right-hand operand's value (0
). The cast is to prevent a warning about N_i
being discarded.
Upvotes: 60