Вопрос

Мне необходимо использовать std::function Но я не знаю, что означает следующий синтаксис.

std::function<void()> f_name = []() { FNAME(); };

Какова цель использования std::function? Это указывает на функцию?

Это было полезно?

Решение

std::function это объект стирания типа. Это означает, что он стирает детали того, как происходят некоторые операции, и предоставляет им единый интерфейс времени выполнения. За std::function, Главная1 Операции - это копия/перемещение, разрушение и «вызов» с operator() - Функция как оператор вызова '.

На менее заумном английском это означает, что std::function может содержать практически любой объект, который действует как указатель функции в том, как вы его называете.

Подпись, которую она поддерживает, заходит внутри угловых кронштейнов: std::function<void()> Понимает нулевые аргументы и ничего не возвращает. std::function< double( int, int ) > берет два int аргументы и возврат double. Анкет В целом, std::function Поддерживает хранение любого функционального объекта, аргументы которых могут быть преобразованы в список аргументов, и возвращаемое значение которого можно преобразовать в его возвратное значение.

Важно знать, что std::function и Lambdas разные, если совместимы, звери.

Следующая часть линии - лямбда. Это новый синтаксис в C ++ 11, чтобы добавить возможность писать простые функциональные объекты-объекты, которые можно вызвать с помощью (). Анкет Такие объекты могут быть стерты и хранятся в std::function За счет некоторого времени на накладные расходы.

[](){ code } В частности, действительно простая лямбда. Это соответствует этому:

struct some_anonymous_type {
  some_anonymous_type() {}
  void operator()const{
    code
  }
};

экземпляр вышеуказанного простого псевдофункционального типа. Фактический класс, подобный вышеуказанному, «изобретен» компилятором, с реализацией, определенной уникальным именем (часто включающим символы, которые не может содержать, определяемый пользователем) (я не знаю, возможно ли вы следовать стандарту без изобретения Такой класс, но каждый компилятор, о котором я знаю, на самом деле создает класс).

Синтаксис полного Lambda выглядит как:

[ capture_list ]( argument_list )
-> return_type optional_mutable
{
  code
}

Но многие части могут быть опущены или оставлены пустыми. Capture_list соответствует как конструктору результирующего анонимного типа, так и его переменных членов, аргумент operator(), и вернуть тип возврата типа. Конструктор экземпляра Lambda также волшебным образом называется, когда экземпляр создается с помощью capture_list.

[ capture_list ]( argument_list ) -> return_type { code }

в основном становится

struct some_anonymous_type {
  // capture_list turned into member variables
  some_anonymous_type( /* capture_list turned into arguments */ ):
    /* member variables initialized */
  {}
  return_type operator()( argument_list ) const {
    code
  }
};

Обратите внимание, что в Шаблонные аргументы были добавлены в Lambdas, и это не покрыто выше.

[]<typename T>( std::vector<T> const& v ) { return v.size(); }

1 Кроме того, хранится RTTI (TypeID), и входит операция типа листа в оригинальном типе.

Другие советы

Давайте разберем линию на части:

std :: function

Это объявление для функции, не принимающей параметров, и не возвращает значение. Если функция вернула int, это выглядело бы так:

std::function<int()>

Точно так же, если он также занял параметр int:

std::function<int(int)>

Я подозреваю, что ваша главная путаница - следующая часть.

[]() { FNAME(); };

А [] часть называется пункт захвата. Анкет Здесь вы помещаете переменные, которые являются локальными для объявления вашей Lambda, и что вы хотите быть доступным в пределах Lambda функционирует сама. Это говорит: «Я не хочу, чтобы что -то было захвачено». Если бы это было в определении класса, и вы хотели, чтобы класс был доступен для Lambda, вы могли бы сделать:

[this]() { FNAME(); };

Следующая часть - это параметры, передаваемые Lambda, точно так же, как если бы это была обычная функция. Анкет Как упоминалось ранее, std::function<void()> это подпись, указывающая на метод, который не принимает параметров, так что это также пусто.

Остальная часть - это тело самого лямбды, как будто это была обычная функция, которую мы можем видеть, просто вызывает функцию FNAME.

Другой пример

Допустим, у вас была следующая подпись, то есть для чего -то, что может суммировать два числа.

std::function<int(int, int)> sumFunc;

Теперь мы могли бы объявить лямбду таким образом:

sumFunc = [](int a, int b) { return a + b; };

Не уверен, что вы используете MSVC, но вот ссылка на синтаксис выражения Lamda:

http://msdn.microsoft.com/en-us/library/dd293603.aspx

Lambdas с захватами (Stateful Lambdas) не могут быть назначены друг другу, поскольку они имеют уникальные типы, даже если они выглядят точно так же. Чтобы иметь возможность хранить и передавать лямбдас с захватами, мы можем использовать »std :: function«Чтобы удерживать функциональный объект, построенный выражением Lambda. В основном»std :: function«Это возможность назначать функции Lambda различными структурами содержимого функциональному объекту Lambda.

Exp:

auto func = [](int a){
 cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //ATTENTION(ERROR!): assigning a new structure to the same object
 cout << "x:" << x << ",a:" << a << endl;
};
func(2);

Таким образом, вышеупомянутое использование будет неверным. Но если мы определим объект функции с помощью "std :: function":

auto func = std::function<void(int)>{};
func = [](int a){
  cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //CORRECT. because of std::function
  //...
}; 

int y = 11;
func = [x,y](int a){ //CORRECT
 //...
}; 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top