Я не уверен, что мое объяснение будет на 100% точным, но если нет, надеюсь, кто-то разъяснит это. Вместо std::string
и char*
я буду использовать собственный класс Y
и int
для простоты:
struct Y
{
Y(int) { }
};
struct X
{
operator int() const { return 1; }
operator Y() const { return Y(0); }
};
int main()
{
X x;
Y y(x);
}
С этим кодом в C ++ 11 / 14 , у компилятора есть два варианта действий:
Он преобразует x
в Y(0)
на X::operator Y()
, а затем передает этот Y(0)
в движение конструктор Y
.
Он преобразует x
в int(1)
на X::operator int()
и затем передает это int(1)
в конструктор преобразования Y::Y(int)
.
Оба параметра эквивалентны и, следовательно, генерируют неоднозначность, что приводит к ошибке компиляции.
В C ++ 17 , ситуация отличается из-за гарантированного копирования elision . Здесь вызов конструктора перемещения в (1.) равен elided , и, следовательно, выбирается первая последовательность преобразования, поскольку она требует только 1 преобразования вместо 2.
Во всяком случае, эта версия:
Y y(static_cast<Y>(x));
также порождает неоднозначность в C ++ 11/14, что, я должен признать, я не понимаю.