函数是如何工作的

你知道,我们可以把 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 + + 中一个新的有效表达式吗?

10678 次浏览

它使用一些 类型擦除技术类型擦除技术

一种可能性是将子类型和模板混合使用。下面是一个简化的版本,只是为了让你对整个结构有一个感觉:

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)...);
}
};

(注意,为了简单起见,我忽略了几点: 它不能被复制,可能还有其他问题; 不要在实际代码中使用这段代码)