【问题标题】:Generating a sequence of zeros at compile time在编译时生成一个零序列
【发布时间】:2017-03-06 05:34:48
【问题描述】:

我有以下问题:

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

    // ...

    void foo()
    {
      bar( /* 0,...,0 <- sizeof...(N_i) many */);
    }
};

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

【问题讨论】:

    标签: c++ c++14 variadic-templates


    【解决方案1】:
    bar(((void)N_i, 0)...);
    

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

    【讨论】:

    • 你必须尊重 C++ 大师......脱帽致敬
    • @WhiZTiM 我可能是高手,但不是为上述!
    • @SamVarshavchik 这适用于 0,但不适用于任何其他值。答案应尽可能笼统。
    • @SamVarshavchik 你真的认为N_i*0 + 15(N_i, 15) 更清晰吗?除非读者不理解逗号运算符,这是一个很长的镜头,否则我不应该这样认为。另请注意 krzaq 的优点,即由于通常的算术转换,您的扩展模式的类型可能是 size_t 而不是 int
    • 很好的答案,但如果你希望它尽可能“通用”,那么它应该是 foo(f(N_i)...) 它将扩展为每个参数调用 f() .. . 这将允许您将每个参数编辑为任何值。在这种情况下,您刚刚将 f() 特化为固定值。
    【解决方案2】:

    尽管answer by @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();
     }
    

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


    你可以很容易地概括如下:

    template<std::size_t, typename T, T V>
    constexpr T repeat_value = V;
    

    具体情况下的调用是这样的:

    bar(repeat_value<N_i, int, 0>...);
    

    【讨论】:

    • 在它不重复任何内容时将其命名为 repeat_value 似乎不是一个好主意,但话又说回来,std::move 也不会移动任何东西。
    • @hvd Ahahah... 所以,我符合标准。 :-)
    【解决方案3】:

    您也可以使用模板来模拟类似的东西。这是一个非常基本的解决方案,只会创建一个 0 列表,但如果需要,它可以扩展以生成其他序列。

    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...);
        }
    };
    

    这将扩展为与 N_i 参数大小相同的零列表。诚然,界面略有不同。

    有关显示 bar 接收的元素值的完整示例,请参见此处:Live example

    【讨论】:

      猜你喜欢
      • 2015-01-23
      • 1970-01-01
      • 2012-04-14
      • 2021-10-03
      • 1970-01-01
      • 1970-01-01
      • 2013-01-13
      • 1970-01-01
      • 2013-07-23
      相关资源
      最近更新 更多