2013-03-10 12 views
12

Notacja dla std :: function jest całkiem niezła w porównaniu ze wskaźnikami funkcji. Jednak poza tym nie mogę znaleźć przypadku użycia, w którym nie można go zastąpić wskaźnikami. Czy jest to po prostu cukier syntaktyczny dla wskaźników funkcji?Czy istnieje przypadek użycia dla funkcji std ::, która nie jest objęta wskaźnikami funkcji, czy jest to po prostu cukier syntaktyczny?

+4

Jakikolwiek obiekt wywoływalny, który nie jest funkcją? Funkcjonalne funktory, lambdy, wyrażenia wiążące ...? –

+1

std :: function to cukier syntaktyczny dla wszystkich typów funktorów, a nie tylko wskaźników funkcyjnych. – nurettin

+2

@Xeo: odpowiedzi na to pytanie są znacznie lepsze. –

Odpowiedz

24

std::function<> daje możliwość enkapsulacji każdy rodzaj obiektu na żądanie, czyli wskaźniki funkcyjne coś nie może zrobić (choć prawdą jest, że zakaz robienia lambdy można przekształcić funkcjonować wskaźniki).

Aby dać wyobrażenie o rodzaju elastyczność pozwala osiągnąć:

#include <functional> 
#include <iostream> 
#include <vector> 

// A functor... (could even have state!) 
struct X 
{ 
    void operator()() { std::cout << "Functor!" << std::endl; } 
}; 

// A regular function... 
void bar() 
{ 
    std::cout << "Function" << std::endl; 
} 

// A regular function with one argument that will be bound... 
void foo(int x) 
{ 
    std::cout << "Bound Function " << x << "!" << std::endl; 
} 

int main() 
{ 
    // Heterogenous collection of callable objects 
    std::vector<std::function<void()>> functions; 

    // Fill in the container... 
    functions.push_back(X()); 
    functions.push_back(bar); 
    functions.push_back(std::bind(foo, 42)); 

    // And a add a lambda defined in-place as well... 
    functions.push_back([]() { std::cout << "Lambda!" << std::endl; }); 

    // Now call them all! 
    for (auto& f : functions) 
    { 
     f(); // Same interface for all kinds of callable object... 
    } 
} 

jak zwykle zobaczyć live example here. Między innymi, pozwala to na realizację Command Pattern.

+0

Wielkie dzięki, twój przykład ma wiele sensu. –

+0

@static_rtti: OK, cieszę się, że to pomogło :) –

+0

dlaczego jesteś tak niefrasobliwy co do regularnych funkcji? (to jedyny brakujący "!") :-P –

7

std::function jest przeznaczony do reprezentowania dowolnego rodzaju obiektu do wywoływania. Istnieje wiele obiektów do wywoływania, których nie można w żaden sposób przedstawić za pomocą wskaźnika funkcji.

  1. funktora:

    struct foo { 
        bool operator()(int x) { return x > 5; } 
    }; 
    
    bool (*f1)(int) = foo(); // Error 
    std::function<bool(int)> f2 = foo(); // Okay 
    

    Nie można utworzyć instancję foo i przechowywać go w wskaźnik bool(*)(int) funkcyjnego.

  2. lambda z lambda wychwytu:

    bool (*f1)(int) = [&](int x) { return x > y; }; // Error 
    std::function<bool(int)> f2 = [&](int x) { return x > y; }; // Okay 
    

    Jednakże lambda bez chwytania może być przekształcany do wskaźnika funkcji:

    typ zamknięcia do lambda Wyrażenie bez przechwytywania lambda ma publiczną nie-wirtualną jawną funkcję konwersji stałej do wskaźnika do funkcji mającego ten sam parametr i typy zwracane, co operator wywołania funkcji typu zamknięcia. Wartość zwrócona przez tę funkcję konwersji jest adresem funkcji, która po wywołaniu ma taki sam skutek jak wywołanie operatora wywołania funkcji typu zamknięcia.

  3. implementacji zdefiniowane wywoływalne wartości powrotu:

    bool foo(int x, int y) { return x > y; }; 
    
    bool (*f1)(int) = std::bind(&foo, std::placeholders::_1, 5); // Error (probably) 
    std::function<bool(int)> f2 = std::bind(&foo, std::placeholders::_1, 5); // Okay 
    

    std::bind jest wartość powrotna jest obiektem wywoływalnym implementacji zdefiniowane. Tylko jak ten obiekt może być używany, określa standard, a nie jego typ.

Powiązane problemy