下面的代码可以编译并与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/

10-13 08:31
查看更多