2013-08-22 10 views
9

Chcę wywołać metodę z innej, za pośrednictwem funkcji innej firmy; ale oba używają szablonów variadic. Na przykład:Jak łączyć szablony std :: bind(), variadic i perfekcyjne przekazywanie?

void third_party(int n, std::function<void(int)> f) 
{ 
    f(n); 
} 

struct foo 
{ 
    template <typename... Args> 
    void invoke(int n, Args&&... args) 
    { 
    auto bound = std::bind(&foo::invoke_impl<Args...>, this, 
          std::placeholders::_1, std::forward<Args>(args)...); 

    third_party(n, bound); 
    } 

    template <typename... Args> 
    void invoke_impl(int, Args&&...) 
    { 
    } 
}; 

foo f; 
f.invoke(1, 2); 

Problem polega na tym, że pojawia się błąd kompilacji:

/usr/include/c++/4.7/functional:1206:35: error: cannot bind ‘int’ lvalue to ‘int&&’ 

Próbowałem za pomocą lambda, ale maybe GCC 4.8 nie obsługuje jeszcze składni; tutaj jest to, co starałem:

auto bound = [this, &args...] (int k) { invoke_impl(k, std::foward<Args>(args)...); }; 

pojawia się następujący błąd:

error: expected ‘,’ before ‘...’ token 
error: expected identifier before ‘...’ token 
error: parameter packs not expanded with ‘...’: 
note:   ‘args’ 

Z tego co rozumiem, kompilator chce instancję invoke_impl z rodzaju int&&, a ja myślałem, że za pomocą && w tym przypadku zachowa rzeczywisty typ argumentu.

Co robię źle? Dzięki,

+0

GCC 4.8 doskonale obsługuje składnię. Co próbowałeś? –

+0

@ArneMertz Zaktualizowałem pytanie za pomocą składni, którą wypróbowałem – piwi

+0

wydaje się, że właśnie napotkany błąd w gcc, powinno działać: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41934 –

Odpowiedz

6

Wiązanie z &foo::invoke_impl<Args...> utworzy powiązaną funkcję, która pobiera parametr Args&&, co oznacza wartość r. Problem polega na tym, że przekazany parametr będzie wynosił lvalue, ponieważ argument jest przechowywany jako funkcja składowa jakiejś klasy wewnętrznej.

Aby naprawić, użyj reguł zwijania odwołań, zmieniając &foo::invoke_impl<Args...> na &foo::invoke_impl<Args&...>, aby funkcja składowa przyjęła lwartość.

auto bound = std::bind(&foo::invoke_impl<Args&...>, this, 
         std::placeholders::_1, std::forward<Args>(args)...); 

Here is a demo.

+0

Wygląda na to, że że to rozwiązanie nie działa, jeśli użyję argumentu 'std :: reference_wrapper' jako argumentu, tutaj jest przykład: http://ideone.com/VBxfZd; czy brakuje mi czegoś na temat korzystania z opakowań referencyjnych? – piwi

+0

@piwi Następnie zmień 'Args & ...' na 'Args const & ...'. Nie do końca wiadomo, dlaczego działa. – 0x499602D2

+0

Mój zły, mógłbym wymyślić to ;-) Dzięki. – piwi

Powiązane problemy