Я играл с оптимизацией компилятора и проводником компилятора и заметил следующий недостаток в g ++ 9.3 (протестирован локально). Проблема, похоже, сохраняется в g ++ 10.1 (проверено в проводнике компилятора). Я использую
Обратите внимание на следующий код:
#include <iostream>
#include <iomanip>
constexpr auto fib( auto x )
{
if( x == 0 )
return 0;
else if( x == 1 )
return 1;
else
return fib( x - 1 ) + fib( x - 2 );
}
int main( int argc, char * argv[] )
{
std::cerr << std::setprecision(10) << fib( 47.l );
}
Ссылка на обозреватель компилятора здесь .
Я понимаю, что если бы я поставил 47, вывод аргумента шаблона привел бы к функции int foo( int x )
, но это сохраняется, даже когда я передаю длинный двойной литерал.
Это приводит к переполнению.
Почему компилятор не может сделать вывод во время компиляции, что мой возвращаемый тип должен быть двойным? Я ожидал, что, поскольку fib помечен как constexpr, а я компилирую с -O3, даже если бы я передал целое число, g ++ смог бы вывести, что требуется double, понимая, что fib был экспоненциальным.
Даже если это слишком сложно, почему передача длинного двойного литерала не решает проблему? Я ожидал, что функция поймет, что третья ветвь функции должна возвращать длинное двойное значение, поэтому тип возвращаемого значения должен быть длинным двойным.
Компилятор понимает, что длинное двойное значение требуется только тогда, когда fib изменяется на return 0.l и 1.l примерно так:
constexpr auto fib( auto x )
{
if( x == 0 )
return 0.l;
else if( x == 1 )
return 1.l;
else
return fib( x - 1 ) + fib( x - 2 );
}
Интересно, что изменение только одного из возвратов на длинный двойной литерал, например:
if( x == 0 )
return 0.l;
else if( x == 1 )
return 1;
приводит к следующей ошибке :
error: inconsistent deduction for auto return type: ‘long double’ and then ‘int’
Как это может выдать ошибку, но не первый пример?