Le code suivant, une version simplifiée du code trouvé dans le projet googlemock, ne parvient pas à compiler dans Visual Studio 2015 Update 1, mais il compile sur clang [Apple LLVM version 7.0.0 (clang-700.1.76)].
struct ConvertibleFromAny
{
ConvertibleFromAny(int a_value);
template <typename T>
ConvertibleFromAny(const T& a_value);
};
template <typename T>
struct Matcher
{
Matcher(T value);
};
template <typename Rhs>
struct EqMatcher
{
explicit EqMatcher(const Rhs& rhs);
template <typename Lhs>
operator Matcher<Lhs>() const;
};
int main()
{
EqMatcher<ConvertibleFromAny> em(1);
Matcher<ConvertibleFromAny> m = em;
return 0;
}
L'erreur se produit au niveau du affectation déclaration
Matcher<ConvertibleFromAny> m = em;
et le message d'erreur est
error C2440: 'initializing': cannot convert from 'EqMatcher<ConvertibleFromAny>' to 'Matcher<ConvertibleFromAny>'
note: No constructor could take the source type, or constructor overload resolution was ambiguous
Je peux naïvement voir une ambiguïté entre un appel membre à
EqMatcher<ConvertibleFromAny>::operator Matcher<ConvertibleFromAny>()
et une initialisation conceptuellement similaire à
Matcher<ConvertibleFromAny> m(ConvertibleFromAny<EqMatcher<ConvertibleFromAny>>(em))
Je pense que Clang exclut la deuxième option.
EDIT : Inspiré par le commentaire de T.C., j'ai testé ce qui suit :
struct A
{
};
struct X
{
X(const A&);
};
struct B
{
B(const X&);
};
int main()
{
A a;
B b = a;
}
Il compile avec VS 2015, mais pas avec clang. Je n'ai pas été en mesure de trouver des références qui documentent que l'implémentation de Visual C++ s'écarte intentionnellement de la norme à cet égard.
Est-ce un problème bien connu ?