Дан простой шаблон класса с несколькими неявными функциями преобразования (неявный конструктор и оператор преобразования), как в следующем примере:
template<class T>
class Foo
{
private:
T m_value;
public:
Foo();
Foo(const T& value):
m_value(value)
{
}
operator T() const {
return m_value;
}
bool operator==(const Foo<T>& other) const {
return m_value == other.m_value;
}
};
struct Bar
{
bool m;
bool operator==(const Bar& other) const {
return false;
}
};
int main(int argc, char *argv[])
{
Foo<bool> a (true);
bool b = false;
if(a == b) {
// This is ambiguous
}
Foo<int> c (1);
int d = 2;
if(c == d) {
// This is ambiguous
}
Foo<Bar> e (Bar{true});
Bar f = {false};
if(e == f) {
// This is not ambiguous. Why?
}
}
Операторы сравнения, включающие примитивные типы (bool
, int
), как и ожидалось, неоднозначны - компилятор не знает, должен ли он использовать оператор преобразования для преобразования экземпляра левого класса шаблона в примитивный тип или использовать конструктор преобразования для преобразования тип примитива справа к ожидаемому экземпляру шаблона класса.
Однако последнее сравнение, включающее простую struct
, не является двусмысленным. Зачем? Какая функция преобразования будет использоваться?
Протестировано с компилятором msvc 15.9.7.