以下代碼無法使用 Clang 13 和 MSVC v19.29 VS16.11 編譯,但使用 GCC 11.2 成功編譯。
template <typename...>
concept always_true = true;
template <typename T>
concept refable = always_true<T&>;
static_assert(refable<void>);
神箭
GCC在這里錯了嗎?我希望refable<void>評估為 false,因為它void&在直接背景關系中形成了無效的 type( )。
uj5u.com熱心網友回復:
static_assert(refable<void>);
根據[temp.names]/8,refable<void>是一個概念 id:
一個概念 ID是一個簡單模板 ID,其中模板名稱是一個概念名稱。一個概念-ID是型別的prvalue
bool,并沒有指定模板專業化。一個概念-ID的計算結果為true,如果這個概念的歸一化約束的表達被指定的模板引數和滿足([temp.constr.constr])false,否則。
因此,概念的規范化不依賴于命名概念的給定概念 ID中的模板引數,而是獨立執行的;然而,概念 id的使用可能是執行概念規范化的觸發器,[temp.constr.normal]/2:
[注 1:約束運算式的規范化在確定宣告的關聯約束 ([temp.constr.constr]) 和評估命名概念特化 ([expr.prim.id ])。— 尾注]
[temp.constr.normal]/1涵蓋了約束規范化,其中特別是/1.4控制著OP的示例:
運算式 E 的標準形式是一個約束,定義如下:
[...]
/1.4一個的正常形式概念-ID
C<A1, A2, ..., An>是的約束運算式的普通形式C,用后A1, A2, ..., An對C的各自模板引數在每個原子約束的引數映射。如果任何此類替換導致無效型別或運算式,則程式格式錯誤;不需要診斷。[示例1:
template<typename T> concept A = T::value || true; template<typename U> concept B = A<U*>; template<typename V> concept C = B<V&>;
B的約束運算式的規范化是有效的,并導致T?::?value(帶有映射T?U*)∨ true(帶有空映射),盡管運算式T?::?value對于指標型別是不正確的T。C的約束運算式的規范化導致程式格式錯誤,因為它會V&*在引數映射中形成無效型別。— 結束示例]
這里的關鍵問題是 OP 的示例是否遇到
在每個原子約束的引數映射中替換 [...] 。如果任何此類替換導致無效型別或運算式,則程式格式錯誤;不需要診斷。
或不。
refable然而, 的約束運算式的規范化導致true(帶有空映射),重點是這個規范化約束中的空映射。因此,OP 的refable<void> concept-id的范式將代void入 的范式的引數映射refable,但這僅包含一個空引數映射。因此程式不是病態的,NDR 在 [temp.constr.normal]/1.4 下,并且引數映射永遠不會失敗,因為在單個空映射中沒有什么可以替代。
問題是否
refable<void>
結果是否滿足 ( true) 約束 ( false) 歸結為如何解釋[temp.constr.atomic]/3:
To determine if an atomic constraint is satisfied, the parameter mapping and template arguments are first substituted into its expression. If substitution results in an invalid type or expression, the constraint is not satisfied. [...]
This one is a bit tricky to read unambiguously (particularly the emphasized part), but as the parameter mapping is empty, there can be no substitution failure regarding the parameter mapping, and I interpret the emphasized part as substitution of template arguments into the normalized constraint-expression, which contains no template parameters, meaning there is no substitution failure. This would argue for GCC actually being correct to accept the program.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/346450.html
下一篇:為什么要編譯?cout<"是";
