2013-04-23 21 views
9

Grałem w całość z std :: function i std :: bind i zauważyłem coś nieintuicyjnego i chciałbym to lepiej zrozumieć.Zrozumienie std :: function i std :: bind

Na przykład:

void fun() 
{ 
} 

void hun(std::string) 
{ 
} 

int main() 
{ 

    function<void(int)> g = &fun; //This fails as it should in my understanding. 

    function<void(int)> f = std::bind(fun); //This works for reasons unknown to me  
    function<void(int, std::string)> h = std::bind(hun); //this doesn't work 

return 0; 
} 

Jak to możliwe, aby powiązać function<void(int)> do funkcji, która jest void(). Mogłem wtedy zadzwonić do f (1) i się zabawić(). Chciałbym zrozumieć, jak to się robi. Wdrażanie tego w Microsoft Visual Studio 2012 spowodowało, że zagubiłem się w morzu nieczytelnych makr. dlatego właśnie zadaję to pytanie tutaj.

+0

Używam wersji Express Express vs2012. – Alex

+0

czy możesz polecić taką stronę pls? – Alex

+0

Kompiluje się z _clang_ i _g ++ _ oba. +1, ciekawa sytuacja. – soon

Odpowiedz

7

Jeśli nie użyjesz symboli zastępczych argumentu (_1, _2, ...), wszystkie argumenty przekazane do obiektu funkcji zwróconego z std::bind zostaną po prostu odrzucone. Z:

std::function<void(int)> f = std::bind(fun, std::placeholders::_1); 

Otrzymuję (długi i brzydki) błąd zgodnie z oczekiwaniami.

Dla osób zainteresowanych Standardese:

§20.8.9.1.2 [func.bind.bind]

template<class F, class... BoundArgs> 
*unspecified* bind(F&& f, BoundArgs&&... bound_args); 

P3 Powroty: wezwanie spedycja wrapper g ze słabym typu wynik (20.8.2). Efekt g(u1, u2, ..., uM) wynosi INVOKE(fd, v1, v2, ..., vN, result_of<FD cv (V1, V2, ..., VN)>::type) gdzie cv reprezentuje CV -qualifiers z gi wartości i typy argumentów v1, v2, ..., vN Związane są takie jak określono poniżej.

p10 Wartości związane argumentów v1, v2, ..., vN i ich odpowiednich typów V1, V2, ..., VNzależy od rodzaju TiD pochodzących od wywołania bind i -qualifiers cv cv owijki połączenia g w następujący sposób:

  • jeśli TiD jest reference_wrapper<T> argument jest tid.get() oraz typ Vi jest T&;
  • , jeśli wartość is_bind_expression<TiD>::value jest true, argumentem jest tid(std::forward<Uj>(uj)...), a jego typ Vi to result_of<TiD cv (Uj...)>::type;
  • , jeśli wartość j z is_placeholder<TiD>::value nie wynosi zero, argumentem jest std::forward<Uj>(uj), a jego typ Vi to Uj&&;
  • w przeciwnym razie jest to tid, a jego typ Vi to TiD cv &.
+0

Co więcej, nawet jeśli std :: function f = std :: bind (fun); kompiluje. Nie można wywołać f: f(); nie kompiluje się. –

+1

@PeterR: Oczywiście, ponieważ podpis do 'f' nakazuje jeden argument. :) – Xeo

6

Owijka Przekazywanie połączeń generowane przez wywołanie funkcji szablonu bind może przyjąć dowolną liczbę dodatkowych parametrów; będą one ignorowane. Efektywna arytmetyczna i minimalna sygnatura wyrażenia bind jest określona przez użyte w jego konstrukcji placeholder i do którego argumentu (ów) można się powołać.

Powiązane problemy