以下兩個程式都被 clang 接受,但被 gcc 和 msvc 拒絕。演示
#include <iostream>
#include <type_traits>
#include <functional>
template <typename T>
class myclass {
public:
void func(const T&) requires true //#1
{
std::cout << "true version";
}
void func(const T&) requires false //#2
{
std::cout << "false version";
}
};
int main(){
myclass<int> obj;
auto mylambda = std::bind(&myclass<int>::func, &obj, 5); //accepted by clang rejected by gcc
mylambda();
}
正如我們所看到的,上面給出的程式被 gcc 拒絕并出現錯誤:
error: no matching function for call to 'bind(<unresolved overloaded function type>, myclass<int>*, int)'
24 | auto mylambda = std::bind(&myclass<int>::func, &obj, 5); //accepted by clang rejected by gcc
如果我們稍微修改一下程式以使用模板引數,程式仍然會被 gcc 和 msvc 拒絕,但會被 clang 接受。演示
#include <iostream>
#include <type_traits>
#include <functional>
template<bool B>
struct S {
void f() requires B { std::cout << "true\n"; } //#1
void f() requires (!B) { std::cout << "false\n"; } //#2
};
int main() {
S<true> obj{};
auto mylambda = std::bind(&S<true>::f, &obj) ; //gcc rejects this but clang accepts this
mylambda();
}
所以我的問題是哪個編譯器在這里(如果有的話)?
uj5u.com熱心網友回復:
該程式格式正確,并且 clang 在接受代碼方面是正確的,因為在我們撰寫的那一刻S<true>,它就知道/修復了兩個成員函式中的哪一個可用。換句話說,對于任何給定S<boolvalue>的 ,保證只有一個成員函式存在于該類S<boolvalue>中。基本上,對于第二個程式,版本#2被丟棄并且不應通過名稱查找來考慮,因此多載集僅包含一個可行的候選者。
因此,當&S<true>::f作為引數寫入/傳遞給std::bind時,知道#1要選擇版本,因為這是唯一的選擇,因為版??本#2被丟棄,因此#2不作為成員函式存在。
相同的推理適用于第一個示例。在第一個示例中,&myclass::func指的是版本#1,因為#1是唯一可用的版本,因為已#2被丟棄。
筆記
另請注意,類模板的非模板成員函式是模板物體,因此在require-clause上述兩個給定程式中都可以使用 。從dcl.decl#4:
僅當宣告符宣告了模板函式([dcl.fct])時, init-declarator 或 member-declarator 中的可選 requires 子句才應存在。當出現在宣告符之后時,要求子句稱為尾隨要求子句。尾隨的 requires 子句引入了將其約束邏輯或運算式解釋為約束運算式而產生的約束運算式。
筆記2
請注意,標準中有一條注釋在其背景關系中modules說:
即使在實體化背景關系([module.context])包括模塊單元。——尾注]
這是 gcc 錯誤報告:
GCC 拒絕涉及 requires 子句的有效程式
這是 msvc 錯誤報告:
MSVC 拒絕涉及 requires 子句的有效程式
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/532076.html
上一篇:在不知道型別的情況下宣告模板指標
下一篇:拒絕來自其他命名空間的所有流量
