Страницы

Пример вреда шаблонного программирования и не только

Попался на глаза пример шаблонного кода на C++

template <typename T>
T tmax(T a, T b) {
    return b < a ? a : b;
}

Я сразу заметил неточность, которая возникнет при использовании дробных чисел

tmax(0.0f, NAN)=NAN
tmax(NAN, 0.0f)=0.0f

По природе неопределённости функция, возвращающая максимальное из двух значений, в обоих случаях должна была бы давать неопределённость. Это может показаться несущественным, но всё это играет большую роль, когда речь заходит о максимальной корректности.

В стандартной библиотеке уже есть воплощение функции max, но неточность с дробями оказалась и в ней

std::max(0.0f, NAN)=0.0f
std::max(NAN, 0.0f)=NAN

Противоположность закономерна и объясняется противоположным расположением операндов.

О том, что это некорректность, а не так и задумано, можно убедиться взглянув на результат специализированной функции.

fmaxf(0.0f, NAN)=0.0f
fmaxf(NAN, 0.0f)=0.0f

Не обошлось без сюрпризов и здесь. Равенство 0 объясняется тем, что NAN трактуется авторами не как неопределённость, а как отсутствие данных, что довольно странно, ведь NAN образуется в операциях, в которых именно создаётся неопределённое число, а не устраняется. Но результат хотя бы одинаковый в обоих случаях, что всё равно лучше шаблонной функции, нарушающей ещё и коммутативность.

Самый правильный результат для float выдаёт такая функция

float mxf(float a, float b) {
    if (a < b || b != b) {
        a = b;
    }
    return a;
}
mxf(0.0f, NAN)=NAN
mxf(NAN, 0.0f)=NAN

Поэкспериментировать можно здесь или здесь.

Комментариев нет:

Отправить комментарий