簡體   English   中英

使用 constexpr + auto 作為返回和參數類型的奇怪類型推導

[英]Weird type deduction using constexpr + auto as return and parameter type

我一直在玩編譯器優化和編譯器資源管理器,並注意到 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,模板參數推導會推導出 function int foo( int x ) ,但是即使我傳遞了一個長的雙精度字,這種情況仍然存在。

這會導致溢出。

為什么編譯器不能在編譯時推斷出我的返回類型應該是雙精度的? 我本來預計,由於 fib 被標記為 constexpr,並且我正在使用 -O3 進行編譯,因此即使我通過了 integer,g++ 也能夠通過意識到 fib 是指數的來推斷出需要雙精度數。

即使上述內容非常困難,為什么傳入一個長的雙字面量也不能解決問題? 我希望 function 能夠意識到 function 的第三個分支必須返回一個 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 );
}

有趣的是,只將其中一個返回值更改為長雙精度字面值,如下所示:

    if( x == 0 )
        return 0.l;
    else if( x == 1 )
        return 1;

導致以下錯誤:

error: inconsistent deduction for auto return type: ‘long double’ and then ‘int’

這怎么會拋出錯誤,但第一個例子不會?

當您像這樣定義 function 時:

constexpr auto f(auto x) 
{
  return 42;
}

編譯器別無選擇,只能將返回類型推斷為int ,因為這是文字42的類型。 如果您使用其他類型的參數調用f並不重要:

f(42.l);  

返回類型仍然是int ,盡管x的類型是long double

但是,您可以明確要求返回類型與參數類型相同:

constexpr auto f(auto x) -> decltype(x)
{
  return 42;
}

現在返回值將轉換為調用f時使用的參數類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM