Я начал строить библиотеку управления разрешениями,
Основная идея заключается в том, что у вас есть какая-то конфигурация, считанная из файла, и на основании этого вы можете выполнить функциональный объект, который будет оборачивать функции «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 bind с параметрами шаблона veriadic, и он имеет работать для любого типа функции.
Цель состоит в том, чтобы объявление функции было похоже на объявление с 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"}