在编译时生成一系列零

abr*_*ert 38 c++ variadic-templates c++14

我有以下问题:

template< size_t... N_i >
class A
{
  public:

    // ...

    void foo()
    {
      bar( /* 0,...,0 <- sizeof...(N_i) many */);
    }
};
Run Code Online (Sandbox Code Playgroud)

我想调用一个函数并向它bar传递sizeof...(N_i)许多参数,这些参数都是零,例如,bar(0,0,0)以防万一sizeof...(N_i) == 3.如何实施?

Col*_*mbo 60

bar(((void)N_i, 0)...);
Run Code Online (Sandbox Code Playgroud)

逗号运算符将丢弃N_i,只产生右侧操作数的值(0).演员表是为了防止N_i被丢弃的警告.

  • @SamVarshavchik适用于0,但不适用于任何其他值.答案应该尽可能一般. (14认同)
  • 你必须尊重C++大师...帽子 (6认同)
  • 很好的答案,虽然如果你想要它尽可能"通用",那么它应该是foo(f(N_i)...),它将扩展为每个参数调用f()...这将允许你编辑每个论证是任何价值.在这种情况下,你只需将f()专门化为固定值. (4认同)
  • @SamVarshavchik你真的认为`N_i*0 + 15`比`(N_i,15)`更清楚?除非读者不理解逗号操作符,这是一个长镜头,我不应该这么认为.另请注意krzaq的优点,即由于通常的算术转换,扩展模式的类型可能是`size_t`而不是`int`. (3认同)
  • @WhiZTiM我可能是高手,但不是上面的! (2认同)
  • @SamVarshavchik可能会采取不同的重载,因为它是一堆`size_t`零 (2认同)
  • @Mgetz我不明白你指的是什么.在上面的代码中,我们已经有了一个包,并且没有理由引入另一个间接层 - 它肯定会变慢. (2认同)

sky*_*ack 9

尽管@Columbo毫无疑问是有趣的答案,但我想建议另一种基于constexpr'd模板变量的可行解决方案:

 #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();
 }
Run Code Online (Sandbox Code Playgroud)

我发现至少更容易阅读,即使它在编译时的性能方面很糟糕.


您可以轻松地将其概括为:

template<std::size_t, typename T, T V>
constexpr T repeat_value = V;
Run Code Online (Sandbox Code Playgroud)

特定情况下的调用如下:

bar(repeat_value<N_i, int, 0>...);
Run Code Online (Sandbox Code Playgroud)

  • @hvd Ahahah ......所以,我符合标准.:-) (3认同)