C++最佳实践 - 函数类型别名std::function<T>或T

5
在C++中声明函数类型别名时,什么被认为是最佳或良好的实践(我知道这部分问题可能是主观的)?要么
using FuncType = void(int, int);

或者

using FuncType = std::function<void(int, int)>;

哪个更具优势?

当作为函数参数(传递为函数对象、lambda表达式、成员函数或全局函数)时,应该如何使用这些类型,例如:

void foo(FuncType&& func) { ... }
void foo(FuncType func) { ... }
void foo(std::function<FuncType> func) { ... }

编辑

我知道上面的例子并不都适用于 #1 和 #2,但这不是重点。我想知道哪个选项更好(以及为什么),如何在将其用作函数参数时传递此类型。

具体应用场景

由于问题似乎太广泛了(我完全理解),因此我将提供有关我的具体情况的更多细节。

我有一个类,其中包含我希望调用的函数向量(很可能是并行的,但我认为这并不重要)。在这个类中,我可以在运行时向向量中添加函数。

例如:

class

Container
{
public:
    using FuncType = std::function<void(const SomeComplexDataType&, int, double)>;

    inline void addFunction(FuncType func)
    {
        _funcs.push_back(func);
    }

    inline void call(const SomeComplexDataType& a, int b, double c)
    {
        for (auto& func : _funcs)
            func(a, b, c);
    }

private:
    std::vector<FuncType> _funcs{};
};

struct HeavyFunctor
{
    // contains some heavy objects    

    void operator()(const SomeComplexDataType& a, int b, double c)
    {
        /* Some heavy workload */
    }
};

int main()
{
    Container c;    
    c.addFunction([](const SomeComplexDataType& a, int b, double c) { /* do something lightweight */ });
    c.addFunction(HeavyFunctor);
    c.call(x, y, z);

    return 0;
}

我应该如何定义 FuncTypeaddFunction 的参数,以及如何将它们存储在向量中(最好的情况下,不复制可调用对象)?


1
只有第一个选项适用于您提供的所有三个示例... - StoryTeller - Unslander Monica
3
如果您想编写这样的函数,请直接使用模板参数。 std::function 会有显著的开销。 - llllllllll
这个问题太宽泛且部分基于个人意见 - 没有人能说哪一个更好,因为有太多的地方其中一个可能比另一个更好,而且你还忽略了许多其他选择(模板参数、函数视图等)。 - Holt
3
问题在于这些并不是互相替代的选择。就像椅子和桌子一样——两者都是家具,但用途不同。 - user7860670
1
Timo,请查看我关于此主题的文章:https://vittorioromeo.info/index/blog/passing_functions_to_functions.html - Vittorio Romeo
显示剩余4条评论
1个回答

0

我个人会使用:

typedef std::function<void(int,int)> FuncType;

并且

void foo(const FuncType &func) { ... }

编辑: 考虑到这篇文章的评论,它并不是性能最佳的选择,因为它需要虚拟调度。


6
“易于使用和性能”的意思是,这个东西看起来容易使用但并不能提高性能。原因有两点:1)std::function需要虚分派才能调用其调用运算符,如果您需要频繁调用函数,则可能会增加(显著的)开销;2)您正在复制func,其中可能包含难以复制的函数对象,如果您不打算存储func,则可能是不必要的。 - Holt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接