Следующий код, упрощенная версия кода, найденная в проекте googlemock, не скомпилируется в Visual Studio 2015 Update 1, но компилируется на 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;
}
Ошибка выполняется в присваивании
Matcher<ConvertibleFromAny> m = em;
и сообщение об ошибке
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
Я могу наивно видеть двусмысленность между вызовом участника на
EqMatcher<ConvertibleFromAny>::operator Matcher<ConvertibleFromAny>()
и инициализация, концептуально похожая на
Matcher<ConvertibleFromAny> m(ConvertibleFromAny<EqMatcher<ConvertibleFromAny>>(em))
Я предполагаю, что clang исключает второй вариант.
EDIT: Вдохновленный T.C. Я протестировал следующее:
struct A
{
};
struct X
{
X(const A&);
};
struct B
{
B(const X&);
};
int main()
{
A a;
B b = a;
}
Он компилируется с VS 2015, но не с clang. Я не смог найти никаких ссылок на эти документы, которые Visual С++-реализация намеренно отклоняется от стандарта в этом отношении.
Является ли это общеизвестной проблемой?