Consider the following example:
#include <iostream>
template<class T>
struct A {};
struct B : public A<int> {};
struct C {
operator B() { return {}; }
};
template<typename U> struct identity { typedef U type; };
template<class T> using identity_t = typename identity<T>::type;
template<class X>
void test(A<X> arg1, A<X> arg2) { // #1
std::cout << "ok1";
}
template<class X>
void test(A<X> arg3, identity_t<A<X>> arg4) { // #2
std::cout << "ok2";
}
int main() {
B a, b;
C c;
test(a, b);
test(b, c);
}
It works fine in GCC and clang (output ok1ok2) but fails in MSVC 2017: Live demo on Godbolt
27 : <source>(27): error C2668: 'test': ambiguous call to overloaded function
20 : <source>(20): note: could be 'void test<int>(A<int>,A<int>)'
15 : <source>(15): note: or 'void test<int>(A<int>,A<int>)'
27 : <source>(27): note: while trying to match the argument list '(B, B)'
Which kind of makes sense (although is surely a bug in MSVC;) and thus brings us to my questions about why and how it works in GCC and clang:
-
How does
test(a, b)select#1whiletest(b, c)-#2? They look like equally good candidates at least in casetest(a, b). -
Why isn't the compiler complaining about two
testinstantiations with an exact same signature?
Aucun commentaire:
Enregistrer un commentaire