Устранение неоднозначности в конструкторе присваивания С++

Описание

У меня есть код, который неоднозначен, когда присутствует определенный конструктор. Но когда я закомментировал указанный конструктор, то компилятор жалуется, что отсутствует необходимый конструктор.

Минимальный рабочий пример

struct X;

struct E{
    E(const double& r){ /* important protocol stuff */ }
    E(const X&);
};

struct X{
    X(){ /* important init stuff */ }
    ~X(){ /* important delete stuff */ }
    //X(const double& r){ *this=E(r); }  // POSITION 1
    X(const X& x){ /* important init stuff */ *this=x; }
    X(const E& e){ /* important init stuff */ *this=e; }
    const X& operator=(const X& x){ return *this=E(x); }
    const X& operator=(const E& e){ /* important stuff */ return *this; }
};

E::E(const X& x){ /* important protocol stuff */ }

E operator+(const E& x, const E& y){ /* important protocol stuff */ return E(1); }
E operator*(const E& x, const E& y){ /* important protocol stuff */ return E(2); }

int main(){
    X x,y;
    x = 3.0;
    X u = 4.0;  // POSITION 2
    y = x + u * 5.0;
    X z = 6.0 + 7.0 * y;
}

Если позиция 1 закомментирована, позиция 2 выдает ошибку.

С включенной позицией 1 возникает ошибка неоднозначности.

По сути, я хочу удалить позицию 1 и с помощью этого double->X выполнить бросок через double->E->X.

Вопросов

  1. Как называется проблема?
  2. Как это исправить?

Что я пробовал:

  • явные ключевые слова перед различными конструкторами. Для E это приводит к ошибкам после позиции 2. Для X это приводит к той же ошибке, что и с закомментированной позицией 1.
  • удаление конструкторов/операторов из определений из X,E. Однако это не решение, потому что мне нужно включить некоторые важные вещи.
  • пробовал разные компиляторы (g++ 8.3.0 и 9.2.0, clang++ 12.0.0). Это не изменило вопроса.

Пожалуйста, уточните, чем "выдает ошибку". Скопируйте и вставьте фактические сообщения об ошибках.

molbdnilo 20.11.2022 12:22

В цепочке неявных преобразований может быть только одно определяемое пользователем неявное преобразование.

molbdnilo 20.11.2022 12:37
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Неоднозначность возникает из-за того, что (в строке x = 3.0;) компилятор не может решить, какой из двух операторов присваивания использовать: с аргументом X& или с аргументом E&, поскольку оба типа параметров могут быть преобразованы из заданного double (потому что и у E, и у X есть конструкторы, принимающие параметр const double&).

Вы можете устранить эту ошибку, предоставив третий оператор присваивания, который принимает аргумент const double&, например:

struct X {
    X() { /* important init stuff */ }
    ~X() { /* important delete stuff */ }
    X(const double& r){ *this=E(r); }  // Now uncommented (required)
    X(const X& x) { /* important init stuff */ *this = x; }
    X(const E& e) { /* important init stuff */ *this = e; }
    const X& operator=(const double& x) { return *this = E(x); } // Add this!
    const X& operator=(const X& x) { return *this = E(x); }
    const X& operator=(const E& e) { /* important stuff */ return *this; }
};

Другие вопросы по теме