Edw*_*ard 0 c++ g++ compiler-optimization c++20
我一直在玩编译器优化和编译器资源管理器,并注意到 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 );
}
Run Code Online (Sandbox Code Playgroud)
编译器资源管理器链接在这里。
我知道如果我放了 47,模板参数推导会推导出 function int foo( int x ),但是即使我传递一个 long double 文字,这种情况仍然存在。
这会导致溢出。
为什么编译器不能在编译时推断出我的返回类型应该是双精度型?我会期望,因为 fib 被标记为 constexpr,并且我正在使用 -O3 进行编译,即使我传递了一个整数,g++ 也能够通过意识到 fib 是指数的来推断出需要一个 double。
即使上述内容非常困难,为什么传入 long double 文字不能解决问题?我希望该函数能够实现该函数的第三个分支必须返回一个 long double,因此返回类型应该是一个 long double。
编译器仅在 fib 更改为返回 0.l 和 1.l 时才意识到需要 long double ,如下所示:
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 );
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,仅将其中一个返回值更改为 long double 文字,如下所示:
if( x == 0 )
return 0.l;
else if( x == 1 )
return 1;
Run Code Online (Sandbox Code Playgroud)
导致以下错误:
error: inconsistent deduction for auto return type: ‘long double’ and then ‘int’
Run Code Online (Sandbox Code Playgroud)
这怎么会抛出错误,但第一个例子不会?
当您定义这样的函数时:
constexpr auto f(auto x)
{
return 42;
}
Run Code Online (Sandbox Code Playgroud)
编译器别无选择,只能将返回类型推导出为int,因为这是文字的类型42。如果您f使用其他类型的参数调用并不重要:
f(42.l);
Run Code Online (Sandbox Code Playgroud)
返回类型仍然是int,尽管 的类型x是long double。
但是,您可以明确要求返回类型与参数类型相同:
constexpr auto f(auto x) -> decltype(x)
{
return 42;
}
Run Code Online (Sandbox Code Playgroud)
现在返回值将被转换为f被调用的参数的类型。