根据模板类型生成 lambda 主体(调用可调用对象并返回)
generate lambdas body (that invokes a callable and returns) depending on template type
我有一个可调用的对象,可能会返回bool
或void
。此对象需要包装在 lambda 中。此 lambda 应始终返回 bool
。如果可调用对象返回bool
则 lambda 返回对象返回的任何内容。否则(如果对象返回void
( lambda 只是调用它并返回 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()
的方法?
非常感谢有关如何简化此代码的任何其他提示。
不是一个很好的解决方案...
我能想象的最好的是单个 lambda 带有一个if constexpr
来分隔两种情况(您标记为 C++11,但您使用的是std::invoke()
,所以您使用的是 C++17,因此您也可以使用 if constexpr
(
template <typename T, typename F, typename ... Args>
typename SFuncInfo<F>::Signature GenerateLambda(F f, T* pObj,
SParamsPack<Args...>)
{
return [pObj, f](Args && ... as) -> bool
{
if constexpr ( std::is_same_v<void,
decltype(std::function{f})::result_type> )
{
std::invoke(f, pObj, std::forward<Args>(as)...);
return true;
}
else
return std::invoke(f, pObj, std::forward<Args>(as)...);
};
}
嗯...如果你不能使用 C++17(所以没有模板推导指南std::function
也没有if constexpr
(,我能想象的最好的是定义两个重载函数接收一个对象,一个用于该对象的方法指针和该方法的参数。
template <typename T, typename ... As1, typename ... As2>
bool callFunc (T * pObj, bool(T::*f)(As1...), As2 && ... args)
{ return (pObj->*f)(std::forward<As2>(args)...); }
template <typename T, typename ... As1, typename ... As2>
bool callFunc (T * pObj, void(T::*f)(As1...), As2 && ... args)
{ (pObj->*f)(std::forward<As2>(args)...); return true; }
如您所见,第一个返回从方法返回的值(bool
值(;第二个调用方法(返回void
(并返回true
。
给定此callFunc()
对,您可以创建单个GenerateLambda()
template <typename T, typename F, typename ... As>
typename SFuncInfo<F>::Signature GenerateLambda (F f, T * pObj,
SParamsPack<As...>)
{
return [pObj, f](As && ... args)
{ return callFunc(pObj, f, std::forward<As>(args)...); };
}
相关文章:
- 是什么让放置新调用对象的构造函数?
- 当我调用对象的方法时,对象的成员会发生变化
- 为什么静态数组成员变量在调用对象的实例后不显示任何内容?
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 如何从构造函数副本 T(const T&)调用对象 T?
- C++17 如何保存泛型可调用对象以供以后使用
- 检查模板中 nullptr 的函数指针,了解任何类型的可调用对象
- 是否可以在编译时初始化对象的 C 样式函数指针,以便它调用对象的成员函数?
- 如何在C++中将可调用对象放入地图中?
- 在销毁期间从另一个线程调用对象上调用方法是否未定义行为?
- 广义 std::function (std::any 表示可调用对象)
- c++ 替换调用对象方法的宏函数
- 将可调用对象传递给采用 std::function 的构造函数
- 双指针在使用 new 时不调用对象构造函数
- 可调用对象作为默认模板参数
- 只需调用对象即可获取对象数据
- 如果用户尝试从 JS 调用对象的未定义函数C++则回调C++代码
- 如何将当前替代类型的 std::variant 传递给可调用对象?
- C++对象本身作为参数调用对象的方法
- 从移交的类调用对象