2012-05-23 10 views
16

Jak powiązać funkcję, która przyjmuje domyślne argumenty, bez określania domyślnych argumentów, a następnie wywoływania bez żadnych argumentów?Czy mogę powiązać funkcję, która przyjmuje domyślne argumenty, a następnie wywołuje ją?

void foo(int a, int b = 23) { 
    std::cout << a << " " << b << std::endl; 
} 

int main() { 
    auto f = std::bind(foo, 23, 34); // works 
    f(); 


    auto g = std::bind(foo, 23); // doesn't work 
    g(); 

    using std::placeholders::_1; 
    auto h = std::bind(foo, 23, _1); // doesn't work either 
    h(); 

} 
+1

Definiuj "nie działa". Kod byłby kompilowany, gdybyś podał różne nazwy zmiennych. –

+0

dlaczego ciągle przenosisz się do f? – 111111

+0

@ R.MartinhoFernandes tak przykro, przykład był niekompletny. zaktualizowany kod – inf

Odpowiedz

20

Zasadniczo, za każdym razem piszesz foo(x) kompilator tłumaczy je do foo(x, 23);. Działa tylko wtedy, gdy masz bezpośrednie połączenie z nazwą funkcji. Nie można na przykład przypisać &foo do void(*)(int), ponieważ sygnatura funkcji to void(int, int). Domyślne parametry nie odgrywają żadnej roli w podpisie. A jeśli przypiszesz ją do zmiennej void(*)(int, int), utracisz informacje o parametrze domyślnym: nie możesz skorzystać z domyślnego parametru przez tę zmienną. std::bind przechowuje void(*)(int, int) gdzieś w trzewiach, a tym samym traci domyślną informację o parametrze.

W C++ nie ma sposobu na uzyskanie wartości domyślnej parametru spoza funkcji, więc utkniesz z ręcznym podawaniem wartości domyślnej po związaniu.

+0

wielkie tło, dzięki. – inf

8

Myślę, że możesz symulować zachowanie, które chcesz, używając lambda.

Coś wzdłuż linii to:

auto g = [](){ foo(23); }; 

EDIT: Tylko sprawdzone i wydaje się działać prawidłowo: http://ideone.com/SPSvi

0

Mam dwa rozwiązania:

1 - można przeciążać foo () i zadzwoń do oryginału z ustawieniami domyślnymi:

void foo(int a, int b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

inline void foo(int a) 
{ 
    foo(a, 23); 
} 

2 - Można użyć zmiennej statycznej jako domyślne, a następnie użyć go w procesie wiązania:

static int foo_default_b = 23; 
void foo(int a, int b = foo_default_b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

auto g = std::bind(foo, 23, foo_default_b); 
g(); 
0

This answer nie zgadza się z odpowiedzią R. Martinho Fernandes ma. Można używać boost::bind rzeczywiście wiążą się z domyślnymi parametrami, wystarczy umieścić w zastępcze, a więc:

boost::bind<void (int, int)>(foo, _1, _2)(12); 

ten wezwie foo(12, 23), jak oczekiwano. Chociaż nie przetestowałem tego konkretnego kodu, zrobiłem coś podobnego w moim kodzie na podstawie odpowiedzi podanej powyżej i działa on pod numerem gcc 4.8.5.

Hmm, Właśnie zauważyłem, że to jest pytanie o std::bind, a nie boost::bind. Nie wiem, jakie są różnice, jeśli takie istnieją.

Powiązane problemy