是否存在 SFINAE 技术来检查几个语句?
Is exists SFINAE technique to check several statement?
在 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 接受一个参数或零参数,return Fn 的类型是否为 bool?
此代码无法编译,因为在示例中 enabled_if_t 中发生替换失败,但我想以某种方式调用 checkBoolConstFn 如果至少有一个语句:
std::is_same_v<invoke_result_t<Fn, const T&>, bool>
或
std::is_same_v<invoke_result_t<Fn>, bool>
正在编译。是否存在一些技术如何做到这一点?
可能是这样的:
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) {}
};
看来你需要的是is_invocable_r_v
,也就是说,我们可以确定是否可以用零参数或const T&
类型的一个参数调用Fn
来产生一个可转换为 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) {}
};
在 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 接受一个参数或零参数,return Fn 的类型是否为 bool?
此代码无法编译,因为在示例中 enabled_if_t 中发生替换失败,但我想以某种方式调用 checkBoolConstFn 如果至少有一个语句:
std::is_same_v<invoke_result_t<Fn, const T&>, bool>
或
std::is_same_v<invoke_result_t<Fn>, bool>
正在编译。是否存在一些技术如何做到这一点?
可能是这样的:
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) {}
};
看来你需要的是is_invocable_r_v
,也就是说,我们可以确定是否可以用零参数或const T&
类型的一个参数调用Fn
来产生一个可转换为 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) {}
};