Pregunta

Es necesario para mí usar std::function Pero no sé qué significa la siguiente sintaxis.

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

¿Cuál es el objetivo de usar std::function? ¿Es para hacer un puntero a una función?

¿Fue útil?

Solución

std::function es un objeto de borrado de tipo. Eso significa que borra los detalles de cómo ocurren algunas operaciones y les proporciona una interfaz de tiempo de ejecución uniforme. Para std::function, el primario1 Las operaciones son copia/movimiento, destrucción y 'invocación' con operator() - El "operador de llamadas de función".

En inglés menos abstruso, significa que std::function Puede contener casi cualquier objeto que actúe como un puntero de función en cómo lo llama.

La firma que admite va dentro de los soportes de ángulo: std::function<void()> Toma cero argumentos y no devuelve nada. std::function< double( int, int ) > toma dos int Argumentos y devoluciones double. En general, std::function Admite almacenar cualquier objeto similar a la función cuyos argumentos se pueden convertir de su lista de argumentos y cuyo valor de retorno se puede convertir en su valor de retorno.

Es importante saber que std::function y los lambdas son bestias diferentes, aunque compatibles.

La siguiente parte de la línea es una lambda. Esta es una nueva sintaxis en C ++ 11 para agregar la capacidad de escribir objetos simples similares a la función: objetos que se pueden invocar con (). Dichos objetos se pueden borrar y almacenar en un std::function A costa de alguna parte de tiempo de ejecución.

[](){ code } En particular es una lambda realmente simple. Corresponde a esto:

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

Una instancia del tipo de pseudofunción simple anterior. La clase real como la anterior es "inventada" por el compilador, con un nombre único definido por implementación (a menudo incluyendo símbolos que ningún tipo definido por el usuario puede contener) (no sé si es posible que pueda seguir el estándar sin inventar Tal clase, pero cada compilador que conozco realmente crea la clase).

La sintaxis Lambda completa se ve como:

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

Pero muchas partes se pueden omitir o dejar vacías. Capture_List corresponde tanto al constructor del tipo anónimo resultante como a sus variables miembros, el argumento_list los argumentos del operator(), y el tipo de retorno el tipo de retorno. El constructor de la instancia de Lambda también se llama mágicamente cuando la instancia se crea con Capture_List.

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

Básicamente se convierte en

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

Tenga en cuenta que en Se agregaron argumentos de plantilla a Lambdas, y eso no está cubierto anteriormente.

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

1 Además, se almacena RTTI (TypeId), y se incluye la operación de tipo de devolución de retorno de origen.

Otros consejos

Desglosemos la línea:

std :: función

Esta es una declaración para una función que no toma parámetros y no devuelve valor. Si la función devolvió un int, se vería así:

std::function<int()>

Del mismo modo, si también tomó un parámetro int:

std::function<int(int)>

Sospecho que su principal confusión es la siguiente parte.

[]() { FNAME(); };

los [] parte se llama un cláusula de captura. Aquí pones variables locales de la declaración de tu lambda, y que quieres estar disponible dentro de La función Lambda en sí. Esto dice "No quiero que se capturen nada". Si esto estuviera dentro de una definición de clase y quería que la clase estuviera disponible para la Lambda, podría hacerlo:

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

La siguiente parte son los parámetros que se pasan a la lambda, exactamente lo mismo que si fuera una función regular. Como se mencionó anteriormente, std::function<void()> es una firma que apunta a un método que no toma parámetros, por lo que esto también está vacío.

El resto es el cuerpo de la lambda en sí, como si fuera una función regular, que podemos ver solo llamas a la función FNAME.

Otro ejemplo

Supongamos que tenía la siguiente firma, eso es para algo que puede resumir dos números.

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

Ahora podríamos declarar una lambda de manera así:

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

No estoy seguro si está usando MSVC, pero aquí hay un enlace de todos modos a la sintaxis de la expresión LAMDA:

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

Las lambdas con capturas (lambdas con estado) no pueden asignarse entre sí, ya que tienen tipos únicos, incluso si se ven exactamente iguales. Para poder almacenar y pasar Lambdas con capturas, podemos usar "std :: función"Para mantener un objeto de función construido por una expresión de lambda. Básicamente"std :: función"Es, para poder asignar funciones lambda con diferentes estructuras de contenido a un objeto de función 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);

Entonces el uso anterior será incorrecto. Pero si definimos un objeto de función con "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
 //...
}; 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top