C++ 对重载函数模板的不明确调用-即使其中一个模板更专业?

C++ 对重载函数模板的不明确调用-即使其中一个模板更专业?,c++,templates,c++11,overloading,C++,Templates,C++11,Overloading,考虑以下几点: #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(siz

考虑以下几点:

#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>{});
}
#包括
模板
使用大小=标准::积分常数;
模板
空隙f(尺寸,尺寸)/(1)
{ }
模板//(2)
空隙f(尺寸,尺寸)
{ }
int main()
{
f(大小{},大小{});
}
gcc和clang都报告该调用不明确。为什么?
(1)
不是比
(2)
更专业吗


注意:我知道这是很容易解决的,如果从+1)>抛出到
(2)
,我就不需要这样做了

毫不奇怪,CWG问题中的一个类似例子解决了这一问题,即:

如果其中一个参数是非二乘方的,则为偏序 应该只考虑专业化的类型:

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
模板结构B{typedef T type;};
模板字符*f3(T,T);//#7.
模板长*f3(T,类型名B::type);//#8.
char*p3=f3(p3,p3);//#9
根据我的推理#9应该产生歧义,因为第二对 是(T,long*)。第二种类型(即long*)取自 #8的专业候选人。EDG和GCC接受了该准则。VC与 BCC发现了一个模棱两可的问题

ICC和VC++都可以编译您的代码。根据目前的措辞,它们是正确的:每一对都是独立处理的,
大小
使
出现在非推断上下文([temp.decrete.type]/(5.3)),推断必然失败,因此
大小
至少与
大小
一样专业,但反之亦然。因此,重载(1)比重载(2)更专业化

因此,ICC和VC++(大概)处理每一个演绎对,并得出结论,对于第二个演绎对,
size\uu
至少没有
size\u
那么专业化

Clang和GCC(大概)认为,对于(1),
From
是从第一个参数推导出来的,因此不需要在第二对中推导出
size.
至少与其对应的参数一样专业。

不是因为
From+1
是不可推导的吗,因此,当根据过载(2)生成的一些唯一值(如
size{},size{}
)进行验证时,推断本身就成功了@PiotrSkotnicki§14.8.2.4/11:“在大多数情况下,所有模板参数都必须有值才能成功演绎,但出于偏序目的,模板参数可能没有值,前提是它不用于用于偏序的类型中。”。[注:在非推断上下文中使用的模板参数被视为已使用。-结束注]“事后看来,该示例与所讨论的示例没有太大关系…@Barry,我会这么说,是的。如果没有,我会感到惊讶。我只是好奇-哪一部分说明对应的对是独立处理的?@PiotrSkotnicki,我想[temp.decrete.partial]/8就足够了:“否则,使用生成的类型
P
A
,然后按照14.8.2.5中的描述进行扣减。”@Columbo I提交为,但我甚至不能完全确定这是一个bug。可能只是忽略了未推导的对,因此(2)-->(1)有效的演绎仅仅是从第一对开始的(非常成功)。