[英]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.