我想檢測一個函式(operator()在我的例子中)是否存在于一個類中,不管它的簽名或者是否可以獲得指向它的指標(如果沒有額外的資訊可能是不可能的,因為它是模板化的或多載的)。以下使用概念的代碼在 MSVC 和 clang 上編譯,但不是在 GCC 上編譯(請參閱下面的 Godbolt 鏈接以獲取錯誤訊息)。這是否應該作業并且GCC不符合要求,或者這不應該作業并且MSVC和clang過于寬松?有趣的是,GCC 不僅對于多載和模板化operator()的 s 失敗,而且對于簡單的仿函式也失敗了。
另請注意,雖然示例代碼使用了采用 的一元函式的變體int,但我希望無論函式簽名如何(它適用于 MSVC 和 clang),這個概念都能正常作業。
在這里試試GCC、clang和MSVC。
背景關系正在使這項作業,它現在在 MSVC 和 clang 上,但不是 GCC。
template <typename C>
concept HasCallOperator = requires(C t)
{
t.operator();
};
struct functor
{
int operator()(int in_)
{ return 1; }
};
struct functorOverloaded
{
int operator()(const int& in_)
{ return 1; }
int operator()(int&& in_)
{ return 1; }
};
struct functorTemplated
{
template <typename... T>
int operator()(const T&... in_)
{ return 1; }
};
template<HasCallOperator T>
struct B {};
int main()
{
B<functor> a;
B<functorOverloaded> b;
B<functorTemplated> c;
}
uj5u.com熱心網友回復:
首先,檢查概念的方法只是static_assert(而不是嘗試實體化受約束的類模板)。
static_assert(HasCallOperator<functor>);
static_assert(HasCallOperator<functorOverloaded>);
static_assert(HasCallOperator<functorTemplated>);
其次,您不能撰寫任何其他非靜態成員函式t.operator()的相同原因:如果您進行類成員訪問,它必須以呼叫結束。所以這只是一個 clang/msvc 錯誤,它允許任何這些。f.fun
如果呼叫運算子多載或函式模板(或兩者) ,則 then&C::operator()將不起作用。
這確實讓人質疑這一點,因為如果沒有反思,我們可以對這些問題給出的答案種類非常有限。您實際上只能解決非多載、非模板呼叫運算子的簡單情況。
然而,有一種方法在這里有效。訣竅與我們在當前案例中遇到的問題相同:如果多載&C::operator()則不起作用。operator()
因此,我們要做的是構造一個如果有一個&C::operator() 將被多載的案例,并反轉檢查。那是:
#include <type_traits>
struct Fake { void operator()(); };
template <typename T> struct Tester : T, Fake { };
template <typename C>
concept HasCallOperator = std::is_class_v<C> and not requires(Tester<C> t)
{
&Tester<C>::operator();
};
HasCallOperator<C>不檢查C,它檢查從兩者繼承C的型別和具有非多載非模板呼叫運算子的型別。if&Tester<C>::operator()是一個有效的運算式,這意味著它參考&Fake::operator(),這意味著C沒有一個。如果C有一個呼叫運算子(無論是多載還是模板,或者兩者都沒有),那么&Tester<C>::operator()將是模棱兩可的。
檢查是為了確保像這樣的is_class_v東西HasCallOperator<int>不是false格式錯誤的。
請注意,這不適用于final課程。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/410974.html
標籤:
上一篇:C 類大小模板推導
下一篇:模板函式多載歧義
