Удаление операторов преобразования

Есть ли способ отключить операторы преобразования? Отмечая их «= delete» портит другие вещи.

Рассмотрим следующий код:

class Foo
{
public:

Foo() :mValue(0) {}
~Foo() = default;
Foo(int64_t v) { mValue = v; }
Foo(const Foo& src) = default;

bool operator==(const Foo& rhs) { return mValue == rhs.mValue; }

/* after commenting these lines the code will compile */
operator int() const = delete;
operator int64_t() const = delete;

private:
int64_t mValue;
};

int main()
{
Foo foo1(5);
Foo foo2(10);
bool b1 = (foo1 == foo2);
bool b2 = (foo1 == 5);
}

Это не скомпилируется, потому что gcc жалуется, что оператор == является неоднозначным:

test.cc: In function ‘int main()’:
test.cc:25:21: error: ambiguous overload for ‘operator==’ (operand types are ‘Foo’ and ‘int’)
bool b2 = (foo1 == 5);
^
test.cc:25:21: note: candidates are:
test.cc:25:21: note: operator==(int, int) <built-in>
test.cc:25:21: note: operator==(int64_t {aka long int}, int) <built-in>
test.cc:10:10: note: bool Foo::operator==(const Foo&)
bool operator==(const Foo& rhs) { return mValue == rhs.mValue; }
^

Однако после комментирования операторов преобразования код будет скомпилирован и хорошо работать.

Первый вопрос: почему удаленные операторы преобразования создают неоднозначность для оператора ==? Я думал, что они должны отключить неявные преобразования Foo -> int, но, похоже, они влияют на преобразования int -> Foo, что не звучит для меня логично.

Второй: есть ли способ пометить операторы преобразования как удаленные? Да, не объявляя их — но я ищу способ, которым любой в будущем увидит, что эти преобразования отключены по дизайну.

2

Решение

Вот что я думаю, суть вопроса:

[Dcl.fct.def.delete]:

Программа, которая ссылается на удаленную функцию неявно или явно, кроме как для ее объявления, является неправильно сформированной.

Удаленная функция неявно является встроенной функцией ([dcl.inline]).

[Class.member.lookup / 4]:

Если C содержит декларацию имени f, декларация установлена
содержит каждое объявление f, объявленное в C, которое удовлетворяет
требования языковой конструкции, в которой происходит поиск.

Даже если ты delete функция, вы все еще объявляете это. И объявленная функция будет участвовать в разрешении перегрузки. Только когда это разрешенная перегрузка, компилятор проверяет, был ли он удален.

В вашем случае существует явная неоднозначность, когда присутствуют эти объявления функций.

2

Другие решения

Любое использование удаленной функции некорректно (программа не
компиляции).

Если функция перегружена, сначала выполняется разрешение перегрузки,
и программа плохо работает, если удаленная функция
выбран.

В вашем случае программа не может выбрать конверсию, потому что у вас есть 3 варианта

  • int -> Foo

  • Foo -> int

  • Foo -> int64

Второй вопрос:
Вы можете оставить все как есть, но всегда используйте явное преобразование для int

bool b2 = (foo1 == Foo(5));
3

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector