Как работает функция std::
вы знаете, мы можем обернуть или сохранить лямбда-функцию в 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++?
1 ответ:
Он использует какой-то тип техники стирания.
одна из возможностей заключается в использовании полиморфизма подтипа mix с шаблонами. Вот упрощенная версия, просто чтобы дать представление об общей структуре:
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)...); } };
(обратите внимание, что я проглядел несколько вещей, для простоты: он не может быть скопирован, и, возможно, другие проблемы, не используйте этот код в реальном коде)