我已经开始构建权限管理库了, 基本思想是,您从文件中读取某种配置,并基于此您可以执行一个功能对象,该对象将包装“允许”和“限制”功能。
到目前为止的代码分为几个部分
我有一个权限管理器,它显示给定的“std::string”是否能够执行:
class PermissionManager {
public:
virtual bool canAccess(std::string resource) {return true;};
};
接下来,我有该函数的实际包装器:
template <typename FuncT>
class PermissionFunction {
private:
FuncT m_restrict;
FuncT m_allow;
PermissionManager *m_pManager;
std::string m_resource;
public:
PermissionFunction(const PermissionFunction&) = delete;
PermissionFunction& operator=(const PermissionFunction&) = delete;
PermissionFunction(FuncT r, FuncT a, PermissionManager *man, std::string res)
: m_restrict(r), m_allow(a), m_pManager(man), m_resource(res){
}
template<typename ...ARG>
typename std::result_of<FuncT(ARG&&...)>::type operator()(ARG&&... args){
if(m_pManager->canAccess(m_resource)){
return m_allow(std::forward<ARG>(args)...);
} else {
return m_restrict(std::forward<ARG>(args)...);
}
}
};
所以,用法是这样的:
PermissionManager tpm{};
std::function<void(int)> testRestrict = [](int a){std::cout << "Restrict" << std::endl;};
std::function<void(int)> testAllow = [](int a){std::cout << "Allow" << std::endl;};
PermissionFunction<decltype(testRestrict)> testPerm(testRestrict, testAllow, &tpm, "hi");
for(int i = 0; i <10; i++){
testPerm(i);
}
它对于非成员 std::functions 非常有用,但是当我想用成员函数定义它时,它会变得非常困惑:
class test {
public:
void testato(int i){
std::cout << i << std::endl;
}
PermissionManager perm{};
PermissionFunction<std::function<void(int)>>
permf{
std::bind(&test::testato, this, std::placeholders::_1),
std::bind(&test::testato, this, std::placeholders::_1),
&perm, "hi"};
};
我想知道是否有任何方法可以缩短成员变量类型的使用,我也在考虑使用模板,但我不确定如何使用带有 veriadic 模板参数的 std 绑定(bind),它有适用于任何函数类型。
目标是让函数声明与给定示例中的 std::functions 类似,以便我可以用这种方式定义成员对象:
some_template<decltype(member_f)>
wrapper_member{member_f, member_f, &tpm, "resource"}
其中member_f是类的实际成员函数。理想情况下会推断出类型,但我认为以这种方式重复它也是可以接受的:
some_template<return_t(args_t)>
wrapper_member{member_f, member_f, &tpm, "resource"}
最佳答案
C++20 引入 std::bind_front
它将参数仅绑定(bind)到前导参数,因此不需要使用占位符对象。它可以使您的代码更加简洁。
PermissionFunction<std::function<void(int)>> permf{
std::bind_front(&test::testato, this),
std::bind_front(&test::testato, this),
&perm, "hi"};
可能的 C++17 实现:
#include <tuple>
#include <utility>
template <typename F, typename... Xs>
auto bind_front(F&& f, Xs&&... xs)
{
return [
f = std::forward<F>(f),
xs = std::make_tuple(std::forward<Xs>(xs)...)](auto&&... ys) -> decltype(auto)
{
return std::apply(
f,
std::tuple_cat(xs, std::forward_as_tuple(std::forward<decltype(ys)>(ys)...)));
};
}
关于c++ - 成员函数作为 std::function 传递给模板,绑定(bind)所有参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56539908/