Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating a sequence of zeros at compile time

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?

like image 884
abraham_hilbert Avatar asked Oct 24 '16 12:10

abraham_hilbert


3 Answers

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.

like image 116
Columbo Avatar answered Nov 14 '22 08:11

Columbo


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>...);
like image 35
skypjack Avatar answered Nov 14 '22 09:11

skypjack


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

like image 2
RobClucas Avatar answered Nov 14 '22 08:11

RobClucas