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)中,引发我的问题的部分是sect。 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>()
这样的可变调用应该如何实现和C ++ 17编写函数的方法是
template<auto... Vals>
constexpr auto sum() noexcept(noexcept((Vals + ...)))
{
return (Vals + ...);
}
其中template<auto... Vals>
说我们有一个可变参数模板的值,而(Vals + ...)
是一个fold expression,它将所有的值加在一起(外部()
是制作有效折叠表达式所必需的)。
我使用了auto...
,因此它不仅限于特定类型。如果需要,可以添加SFINAE以将模板限制为仅支持添加的类型,否则如果不能将参数包中的所有类型添加到一起,则只会出现编译器错误。