我已经开始构建权限管理库, 基本思想是,您可以从文件中读取某种配置,并基于此配置可以执行将包装“ allow”和“ restrict”功能的功能对象。
到目前为止的代码分为几部分
我有一个权限管理器,它说明是否可以执行给定的“ 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"};
};
我想知道是否有任何方法可以缩短成员变量类型的使用,我也在考虑使用模板,但是我不确定如何将std绑定与普通模板参数一起使用,它具有适用于任何功能类型。
目标是使函数声明类似于给出的示例中带有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"}
答案 0 :(得分:4)
C ++ 20引入了std::bind_front
,该方法仅将参数绑定到前导参数,因此不需要使用占位符对象。它可以用来使您的代码更简洁。
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<decltype(ys)>(ys)...));
};
}