c++ - std::function 的工作原理

标签 c++ c++11

你知道,我们可以将 lambda 函数包装或存储到 std::function:

#include <iostream>
#include <functional>
int main()
{
    std::function<float (float, float)> add = [](float a, float b)
    //            ^^^^^^^^^^^^^^^^^^^^
    {
        return a + b;
    };

    std::cout << add(1, 2) << std::endl;
}

我的问题是关于std::function,你可以看到它是一个模板类,但它可以接受任何类型的函数签名

例如float(float, float)这种形式的return_value(first_arg, second_arg)

std::function 的结构是什么,它如何接受像 x(y,z) 这样的函数签名,以及它如何与它一起工作? float (float, float) 是 C++ 中新的有效表达式吗?

最佳答案

它使用了一些 type erasure technique .

一种可能性是将混合子类型多态性与模板一起使用。这是一个简化的版本,只是为了给大家一个整体结构的感觉:

template <typename T>
struct function;

template <typename Result, typename... Args>
struct function<Result(Args...)> {
private:
    // this is the bit that will erase the actual type
    struct concept {
        virtual Result operator()(Args...) const = 0;
    };

    // this template provides us derived classes from `concept`
    // that can store and invoke op() for any type
    template <typename T>
    struct model : concept {
        template <typename U>
        model(U&& u) : t(std::forward<U>(u)) {}

        Result operator()(Args... a) const override {
            t(std::forward<Args>(a)...);
        }

        T t;
    };

    // this is the actual storage
    // note how the `model<?>` type is not used here    
    std::unique_ptr<concept> fn;

public:
    // construct a `model<T>`, but store it as a pointer to `concept`
    // this is where the erasure "happens"
    template <typename T,
        typename=typename std::enable_if<
            std::is_convertible<
                decltype( t(std::declval<Args>()...) ),
                Result
            >::value
        >::type>
    function(T&& t)
    : fn(new model<typename std::decay<T>::type>(std::forward<T>(t))) {}

    // do the virtual call    
    Result operator()(Args... args) const {
        return (*fn)(std::forward<Args>(args)...);
    }
};

(请注意,为了简单起见,我忽略了几件事:无法复制,可能还有其他问题;请勿在实际代码中使用此代码)

关于c++ - std::function 的工作原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14936539/

相关文章:

c# - 在C#项目中使用C++ DLL

c++ - 如何在 C++ 中获取 Windows 7 中所有电源方案的名称?

c++ - 完善转发模板功能

c++ - 错误 83 错误 C2398 : conversion from 'double' to 'float' requires a narrowing conversion

c++ - 我可以在 XCode 4 或 OSX Lion 中使用 C++11 的最新功能吗?

c++ - 是否可以为模板类的模板函数成员起别名?

c++ - 如何将响应式 Qt GUI 与基于 OpenMP 的计算库相结合?

c++ - 编译纯 C 和 C++

c++ - 指针作为函数返回类型的部分特化

c++ - 如何合并两个排序的 vector 并组合重叠元素?