Конференция "Начинающим" » Вызов определённой версии функции из перегруженных [D2005]
 
  • KSergey © (07.02.18 16:25) [0]
    В 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.
    Что, конечно, совсем никак не годится.
  • KSergey © (07.02.18 16:27) [1]
    Причем первым параметром в IntPower идёт именно константа в коде, переменная только степень.

    Да, запись IntPower(10.0, x) - помогает сделать вычисления верными, но это ж дыра, которую легко пропустить. Компилятор-то на запись IntPower(10,  x) никак не реагирует, не предупреждает.
  • Rouse_ © (07.02.18 16:28) [2]
    Через каст, а вообще я по другому делал - прямо бинарным приведением числа как константой
  • Rouse_ © (07.02.18 16:30) [3]
    вот это глянь, там общий принцип http://rouse.drkb.ru/other.php#round
  • KSergey © (07.02.18 16:39) [4]
    Я читал ваши крутые изыскания. Восхитился, скажу честно!

    Понятно, что можно скастить. Понятно, что можно вызов этой функции везде исправить.
    Меня другое пугает:
    1) Нет никакой защиты, что я не напишу неадекватный код через год и это не повезёт выявить в тестах, как в этот раз (тут очень повезло, что был тест с такими специфическими тестовые данными)
    2) Я теперь даже не представляю где еще любимая Delphi подложила мину в новой версии; на IntPower напоролись случайно в тестах; в каких еще стандартных функциях кроется такой же подвох с типами - я даже не представляю. Это ж дыра страшная!
    Надо как-то себя обезопасить от нее более общим образом

    PS
    Я то думал, что строками юникодными проблемы закончатся.
    Всё больше опасаюсь выбранного пути, вероятно таки переписать на C++ было бы вернее. Не потому, что C++, а потому что при портировании имеющегося кода вылезают совершенно не понятные проблемы, теперь уже на ровном месте.
  • KSergey © (07.02.18 17:03) [5]
    Т.е. меня бы устроил видимо один из двух вариантов, если какой-то возможен:
    1) заставить компилятор выдавать ошибку (хотя бы предупреждение), если где-то в коде используется версия функции для Single аргумента
    2) сказать компилятору "все Single интерпретируй как Double"

    Может что-то такое можно придумать?
  • Юрий Зотов © (07.02.18 18:37) [6]
    А нужна ли здесь перегрузка? Нельзя ли оставить только вариант Extended, а остальные убрать? Насколько помню, такие преобразования типов компилятор рулит сам.
  • Юрий Зотов © (07.02.18 18:40) [7]
    Сорри, был невнимателен.
  • Игорь Шевченко © (07.02.18 21:54) [8]

    > В Delphi 10 определены, например, такие 3 версии функции
    > IntPower():


    А вот в самой Delphi пишут:

    function SimpleRoundTo(const AValue: Single; const ADigit: TRoundToRange = -2): Single;
    var
     LFactor: Extended;
    begin
     LFactor := IntPower(10.0, ADigit);
    ...



    И видимо как-то обходятся
  • KSergey © (08.02.18 14:05) [9]
    Для ИШ: Спасибо за пример. В самом деле.

    Для вообще:
    Видно, что чуваки знали и сознательно делали гадость.
    Рад я за дельфи
    И за себя тоже очень рад, что мне придётся еще пристальнее следить за руками самому, а не при помощи компьютера. Сколько еще таких сюрпризов они приготовили.
  • Плохиш © (09.02.18 12:08) [10]
    Я, често говоря, не понял. Подсовываете компилятору константу целого типа и удивляетесь, что компилятор берёт первую найденую перегружаемую функцию, в тип передаваемого параметра которой он смог константу привести.

    PS. Это уже даже не искуственный интелект. Компилятор должен знать хотелку кодера.
  • Игорь Шевченко © (09.02.18 12:40) [11]
    Плохиш ©   (09.02.18 12:08) [10]


    > Я, често говоря, не понял


    Я, честно говоря, не понял, зачем создавать геморрой с перегруженными функциями :)

    Когда перегружаются функции, отличающиеся числом аргументов или типами, которые невозможно перепутать, это еще полбеды, а когда программист должен заботиться сам о наличии костылей при написании кода, чтобы была выбрана верная перегруженная функция, это чересчур.
    Впрочем, у Борландов много забавностей в коде после D5
  • KSergey © (09.02.18 15:02) [12]
    Спасибо Игорю, он лучше меня озвучил суть моего недоумения.
  • Eraser © (09.02.18 20:05) [13]
    самый простой вариант - написать свои функции с разными названиями под каждый тип, которые вызывают перегруженную системную с нужным кастом.
  • Плохиш © (10.02.18 18:18) [14]

    > Игорь Шевченко ©   (09.02.18 12:40) [11]
    > Я, честно говоря, не понял, зачем создавать геморрой с перегруженными
    > функциями :)

    Подозреваю, что разработчикам просто в голову не пришло использовать для целых типов функцию вместо оператора ^
    :-)
 
Конференция "Начинающим" » Вызов определённой версии функции из перегруженных [D2005]
Есть новые Нет новых   [118608   +47][b:0][p:0.001]