c++ - 模板参数推导 : which compiler is right here?

标签 c++ c++11 g++ clang language-lawyer

考虑以下代码:

template<int N>
class Vector
{
};

#include <array>

template<int N>
void doWork(const Vector<N>&, const std::array<int,N>&)
{
}

int main()
{
    std::array<int,3> arr;
    Vector<3> vec;
    doWork(vec,arr);
}

在这里Vector表示在第三方库中定义的类,std::array已知其元素计数为 std::size_t .

我试过用 clang-3.6 和 g++-5.1 编译它。 Clang 毫无怨言地工作,而 g++ 给出以下错误:

test.cpp: In function ‘int main()’:
test.cpp:17:19: error: no matching function for call to ‘doWork(Vector<3>&, std::array<int, 3ul>&)’
     doWork(vec,arr);
                   ^
test.cpp:9:6: note: candidate: template<int N> void doWork(const Vector<N>&, const std::array<int, N>&)
 void doWork(const Vector<N>&, const std::array<int,N>&)
      ^
test.cpp:9:6: note:   template argument deduction/substitution failed:
test.cpp:17:19: note:   mismatched types ‘int’ and ‘long unsigned int’
     doWork(vec,arr);
                   ^
test.cpp:17:19: note:   ‘std::array<int, 3ul>’ is not derived from ‘const std::array<int, N>’

我可以通过转换 N 来解决这个问题至 std::size_tdoWork() 的第二个参数中或调用doWork<3>() ,但这不会教育我。

所以我宁愿先问:哪个编译器就在这里?我真的在代码中做错了什么(所以 clang 太宽容了),还是它确实有效的 C++(所以 g++ 有一个错误)?

最佳答案

我相信 gcc 在这里是正确的,如果我们转到草案 C++11 标准部分 14.8.2.5 [temp.deduct.type] 它说:

If, in the declaration of a function template with a non-type template-parameter, the non-type templateparameter is used in an expression in the function parameter-list and, if the corresponding template-argument is deduced, the template-argument type shall match the type of the template-parameter exactly, except that a template-argument deduced from an array bound may be of any integral type.144 [ Example:

template<int i> class A { /* ... */ };
template<short s> void f(A<s>);
void k1() {
A<1> a;
f(a); // error: deduction fails for conversion from int to short
f<1>(a); // OK
}

[...]

我们可以查看是否将您的代码更改为:

doWork<3>(vec,arr);

gcc 不会发出错误,clang 也不会。

如果我们尝试这个例子:

template<int N>
void doWorkB( std::array<int,N>&)
{
}

//...

doWorkB(arr);

clang 现在会产生一个错误 ( see it live ):

note: candidate template ignored: substitution failure : deduced non-type template argument does not have the same type as the its corresponding template parameter ('unsigned long' vs 'int')
void doWorkB( std::array<int,N>&)
     ^

如果我们交换参数顺序,您的原始案例也会在 clang 中中断:

void doWork( const std::array<int,N>&, const Vector<N>& )

关于c++ - 模板参数推导 : which compiler is right here?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32891471/

相关文章:

c++ - 将 std::forward 与非转发的普通旧引用一起使用

c++ - g++ 标准支持

C++ 使用纯虚函数接收错误, "variable or field ' x' 声明为 void"

android - 避免 android native 代码 (C++) 中的竞争条件

c++ - 不可 move -不可复制对象的 vector 的 move 分配不编译

c++ - if 语句与 if-else 语句,哪个更快?

c++ - 如何检查构造函数/析构函数中是否使用了虚方法?

c++ - 通过宏定义编译标志(C++11 和优化)

c++ - 在Qt/C++中,如何在没有HOSTS文件的Windows上将x.com域重定向到y.com?

C# - 无法访问 C++/CLI .dll 中包含的方法