在 C 17 中,我想在使用 SFINAE 呼叫某些函式之前檢查一些先決條件,例如:
class TestClass
{
public:
bool foo() const { return true; }
bool bar() { return false; }
};
template<typename T>
class Checker
{
public:
template<typename Fn, typename = std::enable_if_t<(std::is_same_v<invoke_result_t<Fn, const T&>, bool>
|| std::is_same_v<invoke_result_t<Fn>, bool>)>>
void checkBoolConstFn(Fn fn) {}
};
int main()
{
auto foo = [](const TestClass&) { return true; };
auto bar = []() { return true; };
Checker<TestClass> checker;
checker.checkBoolConstFn(foo);
checker.checkBoolConstFn(bar);
checker.checkBoolConstFn(&TestClass::foo);
checker.checkBoolConstFn(&TestClass::bar);
return 0;
}
我嘗試檢查:如果 Fn 接受一個引數或零引數,Fn 的回傳型別是布爾型嗎?
此代碼無法編譯,因為在示例中的 enabled_if_t 中發生替換失敗,但如果至少有一個陳述句,我想以某種方式呼叫 checkBoolConstFn:
std::is_same_v<invoke_result_t<Fn, const T&>, bool>
或者
std::is_same_v<invoke_result_t<Fn>, bool>
是編譯。是否存在一些技術如何做到這一點?
uj5u.com熱心網友回復:
看起來您需要的是is_invocable_r_v,即我們可以確定是否Fn可以使用零引數或一個型別的引數呼叫const T&以產生可轉換為的結果bool
template<typename T>
class Checker
{
public:
template<typename Fn,
typename = std::enable_if_t<
(std::is_invocable_r_v<bool, Fn, const T&> ||
std::is_invocable_r_v<bool, Fn>)>>
void checkBoolConstFn(Fn fn) {}
};
演示
uj5u.com熱心網友回復:
像這樣的東西,也許:
template<typename T>
class Checker
{
public:
template <typename Fn, typename = void>
struct InvocableWithT : public std::false_type {};
template <typename Fn>
struct InvocableWithT<
Fn,
std::enable_if_t<std::is_same_v<std::invoke_result_t<Fn, const T&>, bool>>>
: public std::true_type {};
template <typename Fn, typename = void>
struct InvocableWithNone : public std::false_type {};
template <typename Fn>
struct InvocableWithNone<
Fn,
std::enable_if_t<std::is_same_v<std::invoke_result_t<Fn>, bool>>>
: public std::true_type {};
template<
typename Fn,
typename = std::enable_if_t<
std::disjunction_v<InvocableWithT<Fn>, InvocableWithNone<Fn>>>>
void checkBoolConstFn(Fn fn) {}
};
演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/473702.html
