2016-01-19 15 views
6

en aşağıdaki kod parçasını düşünelim:std :: bağlama ve rvalue referans

class Widget{ 
}; 

int main(){ 
Widget w; 
auto lambda = bind([](Widget&& ref){ return; }, std::move(w)); 

return 0; 
} 

ve hata tetikler

no match for call to ‘(std::_Bind<main()::<lambda(Widget&&)>(Widget)>)()’ 
    lambda(); 

Ve benim sorum edilir: Neden hata ortaya çıktı? Her şeyden önce, rvalue referans için açık bir cast yapıyorum - std::move(w) demek istiyorum ve rvalue referans ile argüman alıyorum - Widget&& ref demek istiyorum.

N'aber?

Üstelik aşağıda kod işleri, kılan beni daha endişeli:

class Widget{ 
}; 

int main(){ 
Widget w; 
auto lambda = bind([](Widget& ref){ return; }, std::move(w)); 

return 0; 
} 

cevap

7

Eğer std::bind şematik olarak ne yazmak eğer daha net hale gelebilir.

// C++14, you'll have to write a lot of boilerplate code for C++11 
template <typename FuncT, typename ArgT> 
auto 
bind(FuncT&& func, ArgT&& arg) 
{ 
    return 
    [ 
     f = std::forward<FuncT>(func), 
     a = std::forward<ArgT>(arg) 
    ]() mutable { return f(a); }; // NB: a is an lvalue here 
} 

Eğer std::bind birkaç kez sizinle verir işlev nesnesini çağırabilir yana, “kullanabilir” olamaz bir lvalue referans olarak geçilecek böylece yakalanan argüman. bind'un kendisini bir rengin geçmesi gerçeği, sadece a'un başlatıldığı satırda hiçbir kopya bulunmadığı anlamına gelir.

Örneğini yukarıda gösterilen şematik bind ile derlemeye çalışırsanız, derleyicinizden daha yararlı bir hata iletisi alırsınız.

main.cxx: In instantiation of ‘bind(FuncT&&, ArgT&&)::<lambda()> mutable [with FuncT = main()::<lambda(Widget&&)>; ArgT = Widget]’: 
main.cxx:10:33: required from ‘struct bind(FuncT&&, ArgT&&) [with FuncT = main()::<lambda(Widget&&)>; ArgT = Widget]::<lambda()>’ 
main.cxx:11:31: required from ‘auto bind(FuncT&&, ArgT&&) [with FuncT = main()::<lambda(Widget&&)>; ArgT = Widget]’ 
main.cxx:18:59: required from here 
main.cxx:11:26: error: no match for call to ‘(main()::<lambda(Widget&&)>) (Widget&)’ 
    ]() mutable { return f(a); }; // NB: a is an lvalue here 
         ^
main.cxx:11:26: note: candidate: void (*)(Widget&&) <conversion> 
main.cxx:11:26: note: conversion of argument 2 would be ill-formed: 
main.cxx:11:26: error: cannot bind ‘Widget’ lvalue to ‘Widget&&’ 
main.cxx:18:33: note: candidate: main()::<lambda(Widget&&)> <near match> 
    auto lambda = bind([](Widget&&){ return; }, std::move(w)); 
           ^
main.cxx:18:33: note: conversion of argument 1 would be ill-formed: 
main.cxx:11:26: error: cannot bind ‘Widget’ lvalue to ‘Widget&&’ 
    ]() mutable { return f(a); }; // NB: a is an lvalue here 
1

Eğer bu gibi yazmak gerekir çalışmasını sağlamak için:

#include <functional> 
#include <iostream> 

class Widget{}; 

int main() 
{ 
    Widget a; 
    auto lf = [](Widget&& par){ }; 

    auto f = std::bind 
    (
     lf, 
     std::bind 
     (
      std::move<Widget&>, a 
     ) 
    ); 
    f(); 
    return 0; 
} 

Benim derleyici Kişisel örnek çalışmıyor gcc version 4.9.2 20141101 (Red Hat 4.9.2-1) (GCC)

+1

olduğunu. F(); – Gilgamesz

+0

Bu örneğin işe yaramadığını nasıl anladınız? Derleyicimle başarıyla derledim. Hangi derleyiciyi kullanıyorsunuz? – zaratustra

+0

http://ideone.com/tl8tc3 – Gilgamesz