如何包装一个函数指针和函数对象在通用代码中工作? [英] How does wrapping a function pointer and function object work in generic code?

查看:199
本文介绍了如何包装一个函数指针和函数对象在通用代码中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下模板定义

template <typename Func, typename ReturnType, typename... Arguments>
class Command
{
public:
    Command(Func f) : m_func(f) { }
    ReturnType operator()(Arguments... funcArgs) { return m_func(funcArgs...); }
private:
    Func m_func;
};

给出一个带有gcc 4.7.3的错误信息(错误:field'Command :: m_func'函数类型)实例化时使用以下测试代码:

gives an error message with gcc 4.7.3 (error: field 'Command::m_func' invalidly declared function type) when instantiated with the following test code:

void testFunction(int i, double d)
{
    std::cout << "TestFunctor::operator()(" << i << ", " << d << ") called." << std::endl;
}

int main()
{
    void (&fRef)(int, double) = TestFunction;
    Command<void(int, double), void, int, double> testCommand(fRef);
}

如果我通过没有地址操作符的TestFunction, testCommand构造函数,但是如果我传递一个显式命名的函数指针或使用address-of运算符传递参数,则会消失。我的印象是,这个代码应该工作在现代C + +设计的第5章。

The error message also occurs if I pass TestFunction without the address-of operator into the testCommand constructor, but disappears if I pass either an explicitly named function pointer or use the address-of operator to pass the parameter. I'm under the impression that this code should work given Chapter 5 of Modern C++ Design.

后面的原因是无法存储对函数的引用,但函数指针工作正常?有没有任何解决方法,将允许这个编译,而不失去支持传递函数作为参数的Command的构造函数,以及?

What is the reasoning behind not being able to store a reference to a function, but function pointers work fine? Are there any workarounds that would allow this to compile without losing support for being able to pass functors as arguments to Command's constructor as well?

推荐答案

更改一行可以修复它:

Command<void(*)(int, double), void, int, double> testCommand(fRef);

不同之处在于,您现在正在传递函数指针,而不是函数类型。 (函数不可复制,但指针是)。

The difference is, you're passing a function pointer now, instead of a function type. (Functions aren't copyable, but pointers are).

引用 fRef 衰减

我不建议使用 std :: function 如果性能重要。

I wouldn't suggest using std::function if performance mattered.

查看 在Coliru上现场

See it live on Coliru

请注意,只要稍作改写,就可以让所有工作变得更好:

Note that with a little rewriting, you can make it all work much nicer:

int main()
{
    auto command = make_command(testFunction);
    command(1, 3.14);
}

为此,建议您更改命令模板为:

To do this, I'd suggest changing the Command template to be:

template <typename Func>
class Command
{
    Func m_func;
public:
    Command(Func f) : m_func(f) { }

    template <typename... A> auto operator()(A... args) const 
        -> decltype(m_func(args...)) 
    { return m_func(args...); }
};

现在你可以在 Func 模板参数通过具有工厂函数:

And now you can have type-deduction on the Func template parameter by having a factory function:

template <typename Func> Command<Func> make_command(Func f)
{
    return Command<Func>(f);
}

查看此方法 Live on Coliru 。当然,输出也一样:

See this approach live on Coliru too. Of course, the output it the same:

TestFunctor::operator()(1, 3.14) called.

这篇关于如何包装一个函数指针和函数对象在通用代码中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆