2015 обновление: Или, если вы хотите сохранить возможность преобразования с использованием синтаксиса (double)obj
вместо синтаксиса obj.to_double()
, сделайте функцию преобразования explicit
, добавив префикс к этому ключевому слову. Вам нужно явное приведение, чтобы преобразование сработало. Лично я предпочитаю синтаксис .to_double
, если только преобразование не будет к bool
, потому что в этом случае преобразование используется if(obj)
, даже если оно explicit
, и это значительно более читабельно, чем if(obj.to_bool())
в мое мнение.
Отбросьте оператор преобразования. Это будет вызывать проблемы на всем пути. Есть функция, как
to_double()
Или аналог, который возвращает значение double и явно вызывает эту функцию, чтобы получить значение double.
Для рассматриваемой проблемы есть эта проблема:
obj >= 10
Рассмотрим это выражение. Встроенный оператор сопоставляет первый аргумент определенной пользователем последовательности преобразования для вашего типа с помощью оператора преобразования long double (). Но ваша функция соответствует второму аргументу по стандартной последовательности преобразования из int в long double (интеграл в преобразование с плавающей запятой). Это всегда неоднозначно, когда есть преобразования для двух аргументов, но нет хотя бы одного аргумента, который можно преобразовать лучше, в то время как остальные аргументы не преобразуются хуже для одного вызова. В вашем случае встроенный лучше соответствует второму аргументу, но первый хуже, но ваша функция лучше соответствует первому аргументу, а второму - хуже.
Это сбивает с толку, поэтому вот несколько примеров (преобразования из char в int называются рекламными акциями, которые лучше, чем преобразования из char в нечто иное, чем int, что называется конверсией):
void f(int, int);
void f(long, long);
f('a', 'a');
Вызывает первую версию. Потому что все аргументы для первого могут быть преобразованы лучше. Точно так же следующее все равно будет вызывать первое:
void f(int, long);
void f(long, long);
f('a', 'a');
Потому что первое может быть преобразовано лучше, а второе - не хуже. Но следующее неоднозначно :
void f(char, long);
void f(int, char);
f('a', 'a'); // ambiguous
В этом случае интереснее. Первая версия принимает первый аргумент с точным соответствием. Вторая версия принимает второй аргумент с точным соответствием. Но обе версии не принимают их другой аргумент по крайней мере одинаково хорошо. Первая версия требует преобразования для своего второго аргумента, в то время как вторая версия требует повышения для своего аргумента. Таким образом, несмотря на то, что продвижение лучше конверсии, вызов ко второй версии не удался.
Это очень похоже на ваш случай выше. Даже если стандартная последовательность преобразования (преобразование из int / float / double в long double) на лучше , чем определяемая пользователем последовательность преобразования (преобразование из MyClass в long double), версия вашего оператора не выбрана, поскольку Ваш другой параметр (long double) требует преобразования аргумента, который хуже, чем встроенный оператор для этого аргумента (идеальное соответствие).
Разрешение перегрузки - это сложный вопрос в C ++, поэтому в нем невозможно запомнить все тонкие правила. Но получить грубый план вполне возможно. Я надеюсь, что это поможет вам.