У меня есть последовательность типов, которые я хочу свободно конвертировать друг в друга. Рассмотрим следующий игрушечный пример:
struct A {
int value;
A(int v) : value(v) { }
};
struct B {
int value;
B(int v) : value(v) { }
B(A a) : value(a.value) { }
operator A() const { return A(value); }
};
struct C {
int value;
C(int v) : value(v) { }
C(A a) : value(a.value) { }
C(B b) : value(b.value) { }
operator B() const { return B(value); }
operator A() const { return A(B(*this)); } // <-- ambiguous
};
int main(int argc, const char** argv) {
C c(5);
A a(3);
a = c;
}
Итак, как вы видите, я пытаюсь определить каждый последующий тип, который будет конвертируемым из всех предыдущих типов, используя конструкторы приведения, и конвертируемым во все предыдущие типы, используя операторы приведения. Увы, это не работает, как задумано, как определение C::operator A
является неоднозначным в соответствии с GCC 4.7:
In member function ‘C::operator A() const’:
19:40: error: call of overloaded ‘B(const C&)’ is ambiguous
19:40: note: candidates are:
9:3: note: B::B(A)
6:8: note: constexpr B::B(const B&)
6:8: note: constexpr B::B(B&&)
Изменение выражения на static_cast<A>(static_cast<B>(*this))
ничего не меняет. Удаление этой строки в целом приводит к сообщению об ошибке в main
, поскольку никакая последовательность неявного преобразования не может использовать более одного определенного пользователем преобразования. В моем игрушечном примере я мог выполнить преобразование из C
в A
как бы то ни было, но в моем приложении из реальной жизни это приведет к появлению большого количества дублирующегося кода, поэтому я бы очень хотел найти решение, которое использует другие операторы преобразования.
Итак, как я могу получить набор из трех свободно конвертируемых типов без дублирования кода преобразования?
Я бы попробовал этот способ в структуре C:
operator A() const { return this->operator B(); }
Попробуй это:
operator A() const { return A(B(value)); }
или это:
operator A() const { return A(operator B()); }