将任意lambda表达式传递给函数?

时间:2012-12-01 20:22:52

标签: c++ templates c++11 lambda

我有一个非常奇特的问题,因为我正在尝试创建某种编译器...... 我想将lambda表达式传递给模板化函数,如下所示:

    template<class T>
delegate<T>* bind(std::function<T> func)
{
    return nullptr;
}

所以我现在可以打电话了

bind([&](int a) { // do something });

...通常,这不会有问题,因为std :: function能够捕获lambda。但问题在于(让我们假设)我不知道或者不想提供关于“T”究竟是什么的信息。它可以是任何函数签名,您也可以插入到std :: function&lt;&gt; ...

我还需要将此“推断”签名传递回我想要返回的“委托”类,并且该委托类需要是指向类的指针...

现在我想出了这个:

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”时明确指定“T”参数(然后它至少可以工作)才能使其工作?

由于理论上我的编译器具有解决此问题的所有信息,我只能插入“T”的实例,但这会使生成的代码不必要地复杂化。

BTW,我正在使用最新的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”修饰符。

1 个答案:

答案 0 :(得分:2)

首先,你完全搞砸了你的右值参考。您的转发根本不起作用。

其次,在某些情况下这是不可能的..对于某些函数对象,您可以通过将成员函数指针指向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