![](/img/trans.png)
[英]Requires-clause appears after template template parameter: is this legal grammar?
[英]Substitution failure in an atomic constraint of template function requires-clause
C++20 中的約束在通過將它們划分為原子約束來檢查是否滿足之前進行了規范化。 例如,約束E = E1 || E2
E = E1 || E2
有兩個原子約束E1
和E2
原子約束中的替換失敗應視為原子約束的錯誤值。
如果我們考慮一個示例程序,則concept Complete = sizeof(T)>0
檢查定義的類T
:
template<class T>
concept Complete = sizeof(T)>0;
template<class T, class U>
void f() requires(Complete<T> || Complete<U>) {}
template<class T, class U>
void g() requires(sizeof(T)>0 || sizeof(U)>0) {}
int main() {
f<void,int>(); //ok everywhere
g<void,int>(); //error in Clang
}
那么函數f<void,int>()
滿足要求,因為Complete<void>
由於替換失敗而僅評估為false
而Complete<int>
評估為true
。
但是類似的函數g<void,int>()
使編譯器產生分歧。 GCC 接受它,但 Clang 不接受:
error: no matching function for call to 'g'
note: candidate template ignored: substitution failure [with T = void, U = int]: invalid application of 'sizeof' to an incomplete type 'void'
void g() requires(sizeof(T)>0 || sizeof(U)>0) {}
演示: https : //gcc.godbolt.org/z/zedz7dMGx
函數f
和g
不是真的相同,還是 Clang 在這里錯了?
這是Clang 錯誤 #49513 ; 情況和分析與這個答案類似。
sizeof(T)>0
是原子約束,因此[temp.constr.atomic]/3適用:
為了確定是否滿足原子約束,首先將參數映射和模板參數代入其表達式。 如果替換導致無效的類型或表達式,則不滿足約束。 [...]
sizeof(void)>0
是無效表達式,因此不滿足約束,並且約束評估繼續進行sizeof(U)>0
。
與鏈接的問題一樣,另一種解決方法是使用“ requires requires requires ”; 演示:
template<class T, class U>
void g() requires(requires { requires sizeof(T)>0; } || requires { requires sizeof(U)>0; }) {}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.