繁体   English   中英

在编译时生成一个零序列

[英]Generating a sequence of zeros at compile time

我有以下问题:

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

    // ...

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

我想调用 function bar并将sizeof...(N_i) many arguments 传递给它,这些都是零,例如bar(0,0,0)以防sizeof...(N_i) == 3 如何实施?

bar(((void)N_i, 0)...);

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

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

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

您还可以使用模板来模拟类似的东西。 这是一个非常基本的解决方案,只会创建一个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接收的元素的值,请参见此处: 实例

您还可以使用这样一个事实,即如果我们从其自身中减去任何正数 integer,我们将得到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();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM