下面的代码可以编译并与MSVC 2013一起正常运行,但不能与clang++ 3.6一起运行。
哪个编译器正确?
MSVC 2013编译并执行代码,输出 26.04 :
#include <iostream>
template <typename T, typename ... U>
auto mul(T t, U ... u) -> decltype(t * mul(u ...))
{
return t * mul(u ...);
}
template <typename T>
T mul(T t) { return t; }
int main()
{
std::cout << mul(2., 3.1, 4.2) << std::endl;
}
但是,使用clang++-3.6编译会产生错误:
$ clang++ test.cpp -stdlib=libc++ -Wall -Wextra -std=c++14
prog.cc:14:15: error: no matching function for call to 'mul'
std::cout << mul(2., 3.1, 4.2) << std::endl;
^~~
prog.cc:4:6: note: candidate template ignored: substitution failure [with T = double, U = <double, double>]: use of undeclared identifier 'mul'
auto mul(T t, U ... u) -> decltype(t * mul(u ...))
^ ~~~
prog.cc:10:3: note: candidate function template not viable: requires single argument 't', but 3 arguments were provided
T mul(T t) { return t; }
^
1 error generated.
是否无法使用mul声明来确定返回的typedecl?
最佳答案
首先,如果将main
中的调用替换为mul(2., 3.1)
(两个参数),则您的代码仍无法在Clang和GCC中进行编译。但是在这种情况下,它不会简单地编译,因为单参数mul
是在多参数版本之后声明的。在声明多参数版本时,尚不知道单参数版本。如果将单参数声明移到顶部,则mul(2., 3.1)
调用将编译。之所以进行编译,是因为返回类型规范decltype(t * mul(u ...))
引用了mul
的一个已经完全声明的单参数版本。
其次,带有三个参数mul(2., 3.1, 4.2)
的原始调用不会编译,因为它尝试通过自身(通过两个参数的版本,仍然引用相同的模板)来递归地声明其返回类型。这是不允许的。是的,我们都知道递归定义明确,并最终达到最低谷,但是该语言不允许这样做。 (仍在寻找正式报价...)
关于c++ - 可变参数模板错误-MSVS2013编译,clang-3.5不会,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32291580/