Обновление 2015 г. Или, если вы хотите сохранить возможность преобразования с использованием синтаксиса (double)obj
вместо синтаксиса obj.to_double()
, сделайте функцию преобразования explicit
, добавив к ней префикс с этим ключевым словом. Вам нужно явное приведение, чтобы преобразование сработало. Лично я предпочитаю синтаксис .to_double
, если только преобразование не будет в bool
, потому что в этом случае преобразование используется if(obj)
, даже если это explicit
, и, на мой взгляд, это значительно более читабельно, чем if(obj.to_bool())
.
Отбросьте оператор преобразования. Это вызовет проблемы на всем пути. Иметь функцию, подобную
to_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++, поэтому невозможно запомнить все тонкие правила в нем. Но получить примерный план вполне возможно. Я надеюсь, что это поможет вам.
person
Johannes Schaub - litb
schedule
15.02.2009