1

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

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

所以我现在可以打电话

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

...所以通常情况下,这不会是一个问题,因为 std::function 能够捕获一个 lambda。但这里的问题是(假设)我不知道或不想提供有关“T”到底是什么的信息。它可以是您也可以插入到 std::function<>... 的任何函数签名

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

现在我想出了这个:

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”修饰符。

4

1 回答 1

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?

于 2012-12-01T20:32:52.933 回答