【问题标题】:Is there a use case for std::function that is not covered by function pointers, or is it just syntactic sugar? [duplicate]是否存在函数指针未涵盖的 std::function 用例,还是只是语法糖? [复制]
【发布时间】:2013-02-25 15:41:44
【问题描述】:

与函数指针相比​​,std::function 的符号非常好。但是,除此之外,我找不到不能用指针替换它的用例。那么它只是函数指针的语法糖吗?

【问题讨论】:

  • 任何不是函数的可调用对象?有状态函子、lambda、绑定表达式...?
  • std::function 是所有类型仿函数的语法糖,而不仅仅是函数指针。
  • @Xeo :这个问题的答案要好得多。

标签: c++ c++11 c++-standard-library std-function


【解决方案1】:

std::function<> 使您可以封装任何类型的可调用对象,这是函数指针无法做到的(尽管 非捕获 lambdas 确实可以转换为函数指针)。

让您了解它可以实现的灵活性:

#include <functional>
#include <iostream>
#include <vector>

// A functor... (could even have state!)
struct X
{
    void operator () () { std::cout << "Functor!" << std::endl; }
};

// A regular function...
void bar()
{
    std::cout << "Function" << std::endl;
}

// A regular function with one argument that will be bound...
void foo(int x)
{
    std::cout << "Bound Function " << x << "!" << std::endl;
}

int main()
{
    // Heterogenous collection of callable objects
    std::vector<std::function<void()>> functions;

    // Fill in the container...
    functions.push_back(X());
    functions.push_back(bar);
    functions.push_back(std::bind(foo, 42));

    // And a add a lambda defined in-place as well...
    functions.push_back([] () { std::cout << "Lambda!" << std::endl; });

    // Now call them all!
    for (auto& f : functions)
    {
        f(); // Same interface for all kinds of callable object...
    }
}

像往常一样,请参阅live example here。除此之外,这使您可以实现Command Pattern

【讨论】:

  • 非常感谢,你的例子很有意义。
  • @static_rtti:好的,很高兴它有帮助:)
  • 为什么你对常规函数如此不感兴趣? (这是唯一一个缺少'!'):-P
  • @AlexanderMalakhov:我只是忘了添加它。或者也许我的潜意识觉得它们很无聊;)
【解决方案2】:

std::function 旨在表示任何类型的可调用对象。有很多可调用对象不能用函数指针以任何方式表示。

  1. 函子:

    struct foo {
      bool operator()(int x) { return x > 5; }
    };
    
    bool (*f1)(int) = foo(); // Error
    std::function<bool(int)> f2 = foo(); // Okay
    

    您不能创建foo 的实例并将其存储在bool(*)(int) 函数指针中。

  2. 带有 lambda-capture 的 lambda

    bool (*f1)(int) = [&](int x) { return x > y; }; // Error
    std::function<bool(int)> f2 = [&](int x) { return x > y; }; // Okay
    

    但是,没有捕获的 lambda 可以转换为函数指针:

    没有 lambda-capture 的 lambda 表达式的闭包类型有一个公共的非虚拟非显式 const 转换函数,指向具有与闭包类型的函数调用运算符相同的参数和返回类型的函数的指针。这个转换函数的返回值应该是一个函数的地址,当被调用时,它与调用闭包类型的函数调用运算符具有相同的效果。

  3. 实现定义的可调用返回值:

    bool foo(int x, int y) { return x > y; };
    
    bool (*f1)(int) = std::bind(&foo, std::placeholders::_1, 5); // Error (probably)
    std::function<bool(int)> f2 = std::bind(&foo, std::placeholders::_1, 5); // Okay
    

    std::bind 的返回值是一个实现定义的可调用对象。标准仅指定了该对象的使用方式,而不是其类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    • 2013-02-05
    • 1970-01-01
    • 2017-07-27
    • 2017-02-09
    • 2012-08-31
    • 2012-03-15
    相关资源
    最近更新 更多