C ++ 17标准提到了一个独特的可变参数函数模板
就像f<200, 50, 6>() == 256
。
我认为,这很奇怪,让我看看我是否可以自己编写代码。我的代码很优雅。但是,我的优雅代码无法编译,因此在两个徒劳的小时之后,我编写了以下丑陋的代码:
#include <iostream>
namespace {
template<int A> constexpr int f() {return A;}
template<int A, int B, int... C> constexpr int f() {
if (sizeof...(C)) return A + f<B, C...>();
else return A + B;
}
}
int main() {
int n = f<200, 50, 6>();
std::cout << n << "\n";
return 0;
}
这个丑陋的代码有效,而且很有趣,因为它偶然地教了我sizeof...()
。但是,这不对吗?
每次我尝试更简单的操作时,编译器都会大惊小怪,抱怨名称查找冲突或模板重新定义或其他类似的事情。
我的想法感觉不对。我怀疑我错过了重点。请问我错过了哪一点?
参考
有关信息,在标准(草稿here)中,引起我问题的部分是宗派。 5.13.8(第3和第4段)。但是据我所知,这种挑衅是偶然的。我的问题不是关于这样的标准。我的问题是关于适当而优雅地使用变异函数。
非编译示例
如果您想要我更优雅,更未经编译的代码示例,请参考以下示例:
namespace {
template<> constexpr int f() {return 0;}
template<int A, int... C> constexpr int f() {
return A + f<C...>();
}
}
阅读了编译器的错误消息后,我理解了为什么此特定代码失败,所以这不是我的问题。我的问题是,
f<200, 50, 6>()
这样的可变参数调用应如何正确实施,并且答案 0 :(得分:5)
编写函数的C ++ 17方法是
template<auto... Vals>
constexpr auto sum() noexcept(noexcept((Vals + ...)))
{
return (Vals + ...);
}
其中template<auto... Vals>
表示我们有一个可变的值模板,而(Vals + ...)
是一个fold expression,它将所有值相加(外部()
要求有效的折叠表达式)。
我使用了auto...
,因此它不仅限于特定类型。如果需要,可以添加SFINAE来将模板限制为仅支持加法的类型,否则,如果不能将参数包中的所有类型都不能加在一起,则会出现编译器错误。