考慮一個f<T>洗掉了主模板但定義了一些特化的函式模板。我們可以使用 requires-expression 來測驗是否f<T>已被特化:
template <typename T>
int f() = delete;
template <>
int f<int>() {
return 1;
}
template <typename T>
int g() {
if constexpr (requires { f<T>; }) {
return f<T>();
} else {
return -1;
}
}
int main() { return g<void>(); }
版本 1(godbolt 鏈接),同上:在 clang 上編譯,但不是 gcc 或 msvc。
版本 2(godbolt 鏈接):用它替換requires { f<T>; }現在requires { f<T>(); }也可以在 gcc 上編譯。
版本 3(godbolt 鏈接):用命名概念替換行內 requires-expression,它現在可以在所有三個編譯器上編譯。
我很好奇這些版本中哪些是格式良好的 C 20 代碼,哪些實體代表編譯器錯誤。
uj5u.com熱心網友回復:
好吧,MSVC 肯定是錯的。它認為requires 運算式實際上是正確的。但是[dcl.fct.def.delete]/2說:
隱式或顯式參考已洗掉函式的程式,而不是宣告它,是格式錯誤的。
[注1:這包括隱式或顯式呼叫函式并形成指向函式的指標或成員指標。它甚至適用于未潛在評估的運算式中的參考。對于多載集,僅參考多載決議選擇的函式。虛函式的隱式 odr-use ([basic.def.odr]) 本身并不構成參考。——尾注]
運算式f<T>是一個左值,它參考被洗掉的函式,所以它“參考”它;這是格式錯誤的,應該由requires-expression檢測到。
唯一的問題是,病態是否真的存在于直接的背景關系中。該標準沒有解釋“直接背景關系”是什么意思,但是脫離了通常理解的含義,問題是格式錯誤是洗掉的實體化f<void>(不會在直接背景關系中)還是對那個的參考洗掉的功能(將在直接背景關系中)。我傾向于在這里使用 Clang:實體化本身并不是格式錯誤的,因為它的效果是實體化f<void>,即綜合該專業化的定義(并且定義是宣告),而不是參考它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/531482.html
