我有一个非常奇怪的问题,因为我正在尝试创建某种编译器... 我想将 lambda 表达式传递给这样的模板函数:
template<class T>
delegate<T>* bind(std::function<T> func)
{
return nullptr;
}
这样我就可以打电话了
bind([&](int a) { // do something });
... 所以通常情况下,这不是问题,因为 std::function 能够捕获 lambda。但这里的问题是(让我们假设)我不知道或不想提供关于“T”到底是什么的信息。它可以是您也可以插入到 std::function<>...
中的任何函数签名我还需要将这个“推断的”签名传递回我想返回的“委托(delegate)”类,并且该委托(delegate)类需要是指向类的指针...
现在我想出了这个:
template<class T>
struct delegate : public std::function<T>
{
delegate(const std::function<T>& func) : std::function<T>(func) { }
delegate(const delegate<T>& func) { }
};
template<class T>
delegate<T>* bind(std::function<T>&& func)
{
return new delegate<T>(std::forward<std::function<T>>(func));
}
但上面调用“绑定(bind)”的示例失败并显示“失败的模板参数推导”。在调用“绑定(bind)”时,我如何才能使它工作而不必明确指定“T”参数(至少它可以工作)?
因为理论上我的编译器有解决这个问题的所有信息,我可以只插入“T”的实例,但这会使生成的代码不必要地复杂化。
顺便说一句,我使用的是最新的 Clang 编译器。
这是最终的解决方案:
template<typename T> struct get_signature;
template<typename Mem, typename Ret, typename... Args> struct get_signature<Ret(Mem::*)(Args...) const> {
typedef Ret type(Args...);
};
template<class T>
delegate<typename get_signature<decltype(&T::operator())>::type>* bind(T func)
{
return nullptr;
}
请注意,您可能需要根据需要调整“const”修饰符。
最佳答案
首先,您完全搞砸了右值引用。您的转发根本不起作用。
其次,在某些情况下这是不可能的。对于某些函数对象,您可以通过将成员函数指针指向operator()
并检查其签名来推断签名.但是对于其他人来说,他们会重载并且不起作用。
template<typename T> struct get_signature;
template<typename Mem, typename Ret, typename... Args>
struct get_signature<Ret(Mem::*)(Args...)> {
typedef Ret(Args...) type;
};
template<class T>
delegate<typename get_signature<&T::operator()>::type>* bind(T func)
{
return nullptr;
}
第三,std::bind
?
关于c++ - 将任意 lambda 表达式传递给函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13663381/