-
В Delphi 10 определены, например, такие 3 версии функции IntPower():
function IntPower(const Base: Single; const Exponent: Integer): Single; overload; function IntPower(const Base: Double; const Exponent: Integer): Double; overload; function IntPower(const Base: Extended; const Exponent: Integer): Extended; overload;
Вопрос: как запретить для проекта выбор компилятором например варианта с Single-параметром?
В чем практическая проблема. Есть код:
var d1: Double; d2: Double; ... d1 := 100 * IntPower(10, -2); d2 := 1E8 * d1;
(понятно, что вместо цифр - переменные, цифры написал просто для упрощения иллюстрации) Проблема оказалась в том, что если в D5 вариант для IntPower() был только один, который возвращал Extended и в указанных значениях всё вычислялось хорошо (т.е. в d2 попадало в итоге 1E8, т.к. d1 вычисляется равным 1), то в Delphi 10 в такой записи выбирается видимо версия IntPower() для Single, из-за чего d1 = 0,9999997834, и, соответственно, в d2 уже не 1Е8 получается, а 99999978.34. Что, конечно, совсем никак не годится.
-
Причем первым параметром в IntPower идёт именно константа в коде, переменная только степень.
Да, запись IntPower(10.0, x) - помогает сделать вычисления верными, но это ж дыра, которую легко пропустить. Компилятор-то на запись IntPower(10, x) никак не реагирует, не предупреждает.
-
Через каст, а вообще я по другому делал - прямо бинарным приведением числа как константой
-
-
Я читал ваши крутые изыскания. Восхитился, скажу честно!
Понятно, что можно скастить. Понятно, что можно вызов этой функции везде исправить. Меня другое пугает: 1) Нет никакой защиты, что я не напишу неадекватный код через год и это не повезёт выявить в тестах, как в этот раз (тут очень повезло, что был тест с такими специфическими тестовые данными) 2) Я теперь даже не представляю где еще любимая Delphi подложила мину в новой версии; на IntPower напоролись случайно в тестах; в каких еще стандартных функциях кроется такой же подвох с типами - я даже не представляю. Это ж дыра страшная! Надо как-то себя обезопасить от нее более общим образом
PS Я то думал, что строками юникодными проблемы закончатся. Всё больше опасаюсь выбранного пути, вероятно таки переписать на C++ было бы вернее. Не потому, что C++, а потому что при портировании имеющегося кода вылезают совершенно не понятные проблемы, теперь уже на ровном месте.
-
Т.е. меня бы устроил видимо один из двух вариантов, если какой-то возможен: 1) заставить компилятор выдавать ошибку (хотя бы предупреждение), если где-то в коде используется версия функции для Single аргумента 2) сказать компилятору "все Single интерпретируй как Double"
Может что-то такое можно придумать?
-
А нужна ли здесь перегрузка? Нельзя ли оставить только вариант Extended, а остальные убрать? Насколько помню, такие преобразования типов компилятор рулит сам.
-
Сорри, был невнимателен.
-
> В Delphi 10 определены, например, такие 3 версии функции > IntPower():
А вот в самой Delphi пишут: function SimpleRoundTo(const AValue: Single; const ADigit: TRoundToRange = -2): Single;
var
LFactor: Extended;
begin
LFactor := IntPower(10.0, ADigit);
...
И видимо как-то обходятся
-
Для ИШ: Спасибо за пример. В самом деле.
Для вообще: Видно, что чуваки знали и сознательно делали гадость. Рад я за дельфи И за себя тоже очень рад, что мне придётся еще пристальнее следить за руками самому, а не при помощи компьютера. Сколько еще таких сюрпризов они приготовили.
-
Я, често говоря, не понял. Подсовываете компилятору константу целого типа и удивляетесь, что компилятор берёт первую найденую перегружаемую функцию, в тип передаваемого параметра которой он смог константу привести.
PS. Это уже даже не искуственный интелект. Компилятор должен знать хотелку кодера.
-
Плохиш © (09.02.18 12:08) [10]
> Я, често говоря, не понял
Я, честно говоря, не понял, зачем создавать геморрой с перегруженными функциями :)
Когда перегружаются функции, отличающиеся числом аргументов или типами, которые невозможно перепутать, это еще полбеды, а когда программист должен заботиться сам о наличии костылей при написании кода, чтобы была выбрана верная перегруженная функция, это чересчур. Впрочем, у Борландов много забавностей в коде после D5
-
Спасибо Игорю, он лучше меня озвучил суть моего недоумения.
-
самый простой вариант - написать свои функции с разными названиями под каждый тип, которые вызывают перегруженную системную с нужным кастом.
-
> Игорь Шевченко © (09.02.18 12:40) [11] > Я, честно говоря, не понял, зачем создавать геморрой с перегруженными > функциями :)
Подозреваю, что разработчикам просто в голову не пришло использовать для целых типов функцию вместо оператора ^ :-)
|