Почему lambda init-capture не работает для уникального ptr?

Я пытаюсь использовать функцию init-capture c++14 для перемещения unique_ptr внутри лямбды через захват. По какой-то причине gcc и clang отказываются компилировать мой код, настаивая на том, что я пытаюсь скопировать unique_ptr что, очевидно, не работает. Я думал, что избегание копии было именно точкой init-capture + std::move особенность-на самом деле, проходя unique_ptr - видимому, примером для всех.

что я делаю не так?

#include <functional>
#include <iostream>
#include <memory>
#include <string>

void runFunc(std::function<void()>&& f) {
    auto ff = std::move(f);
    ff();
}

int main() {
    auto ptr = std::make_unique<std::string>("hello worldn");
    runFunc([captured_ptr = std::move(ptr)]() {
        std::cout << *captured_ptr;
    });
}   

выход от ССЗ:

http://coliru.stacked-crooked.com/a/d91a480b2b6428ac

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
In file included from main.cpp:1:0:
/usr/local/include/c++/5.2.0/functional: In instantiation of 'static void std::_Function_base::_Base_manager<_Functor>::_M_clone(std::_Any_data&, const std::_Any_data&, std::false_type) [with _Functor = main()::<lambda()>; std::false_type = std::integral_constant<bool, false>]':
/usr/local/include/c++/5.2.0/functional:1746:16:   required from 'static bool std::_Function_base::_Base_manager<_Functor>::_M_manager(std::_Any_data&, const std::_Any_data&, std::_Manager_operation) [with _Functor = main()::<lambda()>]'
/usr/local/include/c++/5.2.0/functional:2260:19:   required from 'std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = main()::<lambda()>; <template-parameter-2-2> = void; _Res = void; _ArgTypes = {}]'
main.cpp:15:6:   required from here
/usr/local/include/c++/5.2.0/functional:1710:34: error: use of deleted function 'main()::<lambda()>::<lambda>(const main()::<lambda()>&)'
    __dest._M_access<_Functor*>() =
                                  ^
main.cpp:13:43: note: 'main()::<lambda()>::<lambda>(const main()::<lambda()>&)' is implicitly deleted because the default definition would be ill-formed:
     runFunc([captured_ptr = std::move(ptr)]() {
                                           ^
main.cpp:13:43: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = std::__cxx11::basic_string<char>; _Dp = std::default_delete<std::__cxx11::basic_string<char> >]'
In file included from /usr/local/include/c++/5.2.0/memory:81:0,
                 from main.cpp:3:
/usr/local/include/c++/5.2.0/bits/unique_ptr.h:356:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;

выход из clang:

http://coliru.stacked-crooked.com/a/4374988d875fcedc

In file included from main.cpp:1:
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/functional:1711:10: error: call to implicitly-deleted copy constructor of '(lambda at main.cpp:13:13)'
            new _Functor(*__source._M_access<_Functor*>());
                ^        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/functional:1746:8: note: in instantiation of member function 'std::_Function_base::_Base_manager<(lambda at main.cpp:13:13)>::_M_clone' requested here
              _M_clone(__dest, __source, _Local_storage());
              ^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/functional:2260:33: note: in instantiation of member function 'std::_Function_base::_Base_manager<(lambda at main.cpp:13:13)>::_M_manager' requested here
            _M_manager = &_My_handler::_M_manager;
                                       ^
main.cpp:13:13: note: in instantiation of function template specialization 'std::function<void ()>::function<(lambda at main.cpp:13:13), void>' requested here
    runFunc([captured_ptr = std::move(ptr)]() {
            ^
main.cpp:13:14: note: copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor
    runFunc([captured_ptr = std::move(ptr)]() {
             ^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/unique_ptr.h:356:7: note: 'unique_ptr' has been explicitly marked deleted here
      unique_ptr(const unique_ptr&) = delete;
      ^
1 error generated.

1 ответов


, потому что std::function должен быть копируемым:

std::function удовлетворяет требованиям CopyConstructible и CopyAssignable.

и конструктор на вопрос:

инициализирует цель С скопировать of f.

лямбда, которую вы строите (полностью достоверно), имеет unique_ptr членов, что делает его noncopyable. Если ты переписал!--5--> взять произвольный функтор по значению:

template <typename F>
void runFunc(F f) {
    auto ff = std::move(f);
    ff();
}

он будет компилироваться.