簡體   English   中英

通過引用調用`constexpr`成員函數-clang vs gcc

[英]Invoking `constexpr` member function through reference - clang vs gcc

考慮以下示例(代碼段 (0) ):

struct X
{
    constexpr int get() const { return 0; }
};

void foo(const X& x)
{
    constexpr int i = x.get();
}

int main()
{
    foo(X{});
}

上面的示例使用g++ 10.x之前的所有g++版本進行編譯,並且從未在clang++clang++ 錯誤信息是:

 error: 'x' is not a constant expression 8 | constexpr int i = x.get(); |

Godbolt.org 上的現場示例

錯誤類型是有道理的,因為x從來不是foo主體中的常量表達式,但是:

  • X::get()被標記為constexpr並且它不依賴於x的狀態;

  • const X&更改為const X會使代碼與每個編譯器(在 Godbolt.org 上)片段 (1)一起編譯。


當我將X::get()標記為static(在 Godbolt.org 上)片段 (2)時,它變得更加有趣。 隨着這一變化,所有經過測試的g++版本(包括主干)都可以編譯,而clang++仍然總是無法編譯。

所以,我的問題:

  • g++ 9.x在接受代碼段 (0) 時是否正確?

  • 所有編譯器都正確接受代碼片段 (1)嗎? 如果是這樣,為什么參考是重要的?

  • g++ 9.xg++ trunk在接受代碼片段 (2) 時是否正確?

g++ 9.x 在接受代碼片段 (0) 時是否正確?

不。

所有編譯器都正確接受代碼片段 (1) 嗎? 如果是這樣,為什么參考是重要的?

對,他們是。

常量表達式不能使用 id 表達式命名引用,該引用沒有先前的常量表達式初始化或在常量表達式評估期間開始其生命周期。 [expr.const]/2.11在 C++20 中相同

如果您在不涉及任何左值到右值轉換的情況下命名非引用變量,則情況並非如此。 x.get()僅將x稱為左值,並且僅調用實際上並未訪問x任何成員的constexpr函數,因此沒有問題。

g++ 9.x 和 g++ trunk 在接受代碼片段 (2) 時是否正確?

不,因為表達式仍然包含違反上述規則的子表達式x

暫無
暫無

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

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