У меня есть вызываемый объект, который может вернуть bool
или void
. Этот объект нужно обернуть в лямбду. Эта лямбда всегда должна возвращать bool
. Если вызываемый объект возвращает bool
, то лямбда возвращает все, что возвращается объектом. В противном случае (если объект возвращает void
), лямбда просто вызывает его и возвращает true
.
Я попытался максимально упростить приведенный ниже код.
template<class... Params>
struct SParamsPack {};
template <class T> struct SFuncInfo {};
// in the simplified version specialization only for member function
template <class T, class R, class... FuncParams>
struct SFuncInfo<R(T::*)(FuncParams...)> {
using Signature = std::function<bool(FuncParams...)>;
using Ret = R;
using Params = SParamsPack<FuncParams...>;
};
template<class T, class Func, class... Params>
SFuncInfo<Func>::Signature GenerateVoidLambda(Func f, T* pObj, SParamsPack<Params...>)
{
return [pObj, f](Params&&... params) -> bool
{
(pObj->*f)(std::forward<Params>(params)...);
return true;
};
}
template<class T, class Func, class... Params>
SFuncInfo<Func>::Signature GenerateBoolLambda(Func f, T* pObj, SParamsPack<Params...>)
{
return [pObj, f](Params&&... params) -> bool
{
return (pObj->*f)(std::forward<Params>(params)...);
};
}
// bodies of both WrapMemberFunction are almost identical
template<class T, class Func, std::enable_if_t<std::is_same<typename SFuncInfo<Func>::Ret, bool>::value, bool> = true>
SFuncInfo<Func>::Signature WrapMemberFunction(Func f, T* pObj)
{
return GenerateBoolLambda(f, pObj, SFuncInfo<Func>::Params());
}
template<class T, class Func, class = std::enable_if_t<std::is_same<typename SFuncInfo<Func>::Ret, void>::value>>
SFuncInfo<Func>::Signature WrapMemberFunction(Func f, T* pObj)
{
return GenerateVoidLambda(f, pObj, SFuncInfo<Func>::Params());
}
//! Registers a std::function that returns bool.
template<class... Params>
void RegisterCommand(const string& id, std::function<bool(Params...)> f)
{
// Code for registration of command.
}
//! Registers a member function pointer as a command.
template<class T, class Func>
void RegisterCommand(const string& id, Func f, T* pObj)
{
RegisterCommand(id, CommandRegistry::WrapMemberFunction(f, pObj));
}
Вызов пользователя будет выглядеть так:
RegisterCommand("general.create", &SomeObj::OnCreate, pSomeObject);
Код должен соответствовать стандарту C ++ 14.
Так есть ли способ заставить этот код выглядеть лучше? Можно ли избавиться хотя бы от WrapMemberFunction()
или GenerateLambda()
методов?
Любые другие советы по упрощению этого кода приветствуются.