Bar*_*rry 10 c++ templates overloading c++11
考虑以下:
#include <utility>
template <int N>
using size_ = std::integral_constant<int, N>;
template <int From>
void f(size_<From>, size_<From+1> ) // (1)
{ }
template <int From, int To> // (2)
void f(size_<From>, size_<To> )
{ }
int main()
{
f(size_<0>{}, size_<1>{});
}
Run Code Online (Sandbox Code Playgroud)
gcc和clang都认为这个电话含糊不清.为什么?是不是(1)更专业(2)?
注意:我知道这可以通过额外enable_if_t<(To > From+1)>投入轻松修复(2),但我不会想到我需要这样做.
不出所料,CWG 问题中的一个类似示例(即#455)解决了这个问题:
如果其中一个参数是非推导的,则部分排序应仅考虑专业化中的类型:
Run Code Online (Sandbox Code Playgroud)template<typename T> struct B { typedef T type; }; template<typename T> char* f3(T, T); // #7 template<typename T> long* f3(T, typename B<T>::type); // #8 char* p3 = f3(p3, p3); // #9根据我的推理,#9 应该产生歧义,因为第二对是 (T, long*)。第二种类型(即 long*)取自#8 的专业化候选者。EDG 和 GCC 接受了该代码。VC 和 BCC 发现了歧义。
ICC 和 VC++ 都可以编译您的代码。根据当前的措辞,它们是正确的:每一对都是独立处理的,并且由于size_<From+1>出现From在非推导上下文中([temp.deduct.type]/(5.3)),推导必然失败,因此size_<From+1>至少是专门化的但size_<To>反之则不然。因此,重载 (1) 比 (2) 更专业。
因此 ICC 和 VC++(大概)处理每个演绎对并得出结论,对于第二个演绎对,size_<To>至少不像 那样专业化size_<From+1>。
Clang 和 GCC(大概)认为,对于 (1),From是从第一个参数推导出来的,因此不需要在第二对中推导出来,因为size_<To>它至少与它的对应项一样专业。