模板参数推论:哪个编译器在这里? [英] Template argument deduction: which compiler is right here?

查看:42
本文介绍了模板参数推论:哪个编译器在这里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

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 .

Here Vector represents a class which is defined in a third-party library, and std::array is known to take its element count as std::size_t.

我尝试使用clang-3.6和g ++-5.1进行编译.Clang正常工作而没有任何抱怨,而g ++则出现以下错误:

I've tried compiling this with clang-3.6 and g++-5.1. Clang worked without any complaint, while g++ gives the following error:

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>’

我可以通过在 doWork()的第二个参数中将 N 强制转换为 std :: size_t 或调用 doWork< 3>(),但这不会教育我.

I can work around this by doing a cast of N to std::size_t in second parameter of doWork() or calling doWork<3>(), but this wouldn't educate me.

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

So I rather ask first: which compiler is right here? Am I really doing something wrong in the code (so clang is too permissive), or is it indeed valid C++ (so that g++ has a bug)?

推荐答案

如果我们转到C ++ 11标准草案草稿 14.8.2.5 [temp.deduct.type] 它说:

I believe gcc is correct here, if we go to the draft C++11 standard section 14.8.2.5 [temp.deduct.type] it says:

如果在具有非类型的函数模板的声明中template-parameter,非类型templateparameter用于函数参数列表中的表达式,以及如果对应的表达式推导template-argument,template-argument类型应匹配模板参数的类型完全相同,除了从数组绑定推导的模板参数可以是任何整数type.144 [示例:

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
}

[...]

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

and we can see if we change your code to this:

doWork<3>(vec,arr);

gcc不会发出错误,叮当声也不会.

gcc does not issue an error and neither does clang.

如果我们尝试以下示例:

If we try this example:

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

//...

doWorkB(arr);

clang现在会产生错误( 实时查看 ):

clang now produces an error (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分隔:

Your original case also breaks in clang if we swap the parameter order:

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

这篇关于模板参数推论:哪个编译器在这里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆