Reputation: 302757
Consider the following:
#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>{});
}
Both gcc and clang report the call as ambiguous. Why? Isn't (1)
more specialized than (2)
?
Note: I know this is easily fixable with an extra enable_if_t<(To > From+1)>
thrown into (2)
, but I wouldn't have thought I needed to do that.
Upvotes: 10
Views: 403
Reputation: 60979
This was - unsurprisingly - addressed by a similar example in a CWG issue, namely #455:
In case that one of the arguments is non-deuced then partial ordering should only consider the type from the specialization:
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
According to my reasoning #9 should yield ambiguity since second pair is (T, long*). The second type (i.e. long*) was taken from the specialization candidate of #8. EDG and GCC accepted the code. VC and BCC found an ambiguity.
Both ICC and VC++ compile your code. According to current wording, they are correct: Each pair is handled independently, and as size_<From+1>
makes From
appear in a non-deduced context ([temp.deduct.type]/(5.3)), deduction necessarily fails, and hence size_<From+1>
is at least as specialized as size_<To>
but not vice versa. Thus overload (1) is more specialized than (2).
So ICC and VC++ (presumably) process every deduction pair and conclude that, for the second one, size_<To>
is not at least as specialized as size_<From+1>
.
Clang and GCC (presumably) argue that, for (1), From
is deduced from the first argument, and thus need not be deduced in the second pair for size_<To>
to be at leas as specialized as its counterpart.
Upvotes: 3