2015-07-15 2 views
2

Я передаю вектор std::unique_ptr объектов A в качестве параметра для конструктора объектов Obj. Это работает, когда я использую синтаксис std::move, как показано ниже. Однако, если добавить еще один объект в списке параметров конструктора (в mpq_class i в коде ниже), я получаю сообщение об ошибке, который считываетvector <unique_ptr <A>> in constructor - error: call to implicitly-deleted copy constructor

error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<A, std::__1::default_delete<A> >' 

на OS X и

error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Interface; _Dp = std::default_delete<Interface>]’ 

на Linux система.

В функции getVector() создан вектор unique_ptr, затем передается в конструктор Obj, и объекты добавляются в другой вектор и возвращаются.

вопрос поэтому код пытается вызвать конструктор копирования, если я использую std::move для unique_ptrs и как избавиться от него!

Код, который производит ошибку, показан ниже.

// g++ -Wall -O3 -std=c++1y -lgmpxx -lgmp 
#include <vector> 
#include <gmpxx.h> 
#include <gmp.h> 
#include <memory> 
#include <iostream> 

class A { 
public: 
    A(int y) : x(y) {} 
    int x; 
}; 


class Obj { 
public: 
    Obj(mpq_class i, std::vector<std::unique_ptr<A> > v) : number(i), cont(std::move(v)) {} 

    mpq_class number; 
    std::vector<std::unique_ptr<A> > cont; 
}; 


std::vector<Obj> getVector() 
{ 
    std::vector<Obj> result; 
    int M = 3, N = 5; 

    for(int mm = 0; mm < M; mm++) 
    { 
     mpq_class rational; 
     std::vector<std::unique_ptr<A> > abstractObjectsForConstructor; 
     for(int nn = 0; nn < N; nn++) 
     { 
      mpq_class r(mm,nn); 
      rational = r; 
      abstractObjectsForConstructor.push_back(std::make_unique<A>(nn)); 
     } 

     result.emplace_back(rational, std::move(abstractObjectsForConstructor)); 
    } 

    return result; 
} 

int main() 
{ 
    std::vector<Obj> vec = getVector(); 

    for(unsigned int ii = 0; ii < vec.size(); ii++) 
    { 
     for(unsigned int jj = 0; jj < vec[ii].cont.size(); jj++) 
     { 
      std::cout << vec[ii].cont[jj]->x << '\t' << std::endl; 
     } 
    } 


    return 0; 
} 

Сообщение Вся ошибка гласит:

In file included from vector_unique.cpp:2: 
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:265: 
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference:15: 
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:628: 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1645:31: error: 
     call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<A, std::__1::default_delete<A> >' 
      ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); 
          ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1572:18: note: 
     in instantiation of function template specialization 'std::__1::allocator<std::__1::unique_ptr<A, 
     std::__1::default_delete<A> > >::construct<std::__1::unique_ptr<A, std::__1::default_delete<A> >, 
     std::__1::unique_ptr<A, std::__1::default_delete<A> > &>' requested here 
      {__a.construct(__p, _VSTD::forward<_Args>(__args)...);} 
       ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1453:14: note: 
     in instantiation of function template specialization 
     'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > > 
     >::__construct<std::__1::unique_ptr<A, std::__1::default_delete<A> >, std::__1::unique_ptr<A, 
     std::__1::default_delete<A> > &>' requested here 
      {__construct(__has_construct<allocator_type, pointer, _Args...>(), 
      ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1005:25: note: 
     in instantiation of function template specialization 
     'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > > 
     >::construct<std::__1::unique_ptr<A, std::__1::default_delete<A> >, std::__1::unique_ptr<A, 
     std::__1::default_delete<A> > &>' requested here 
     __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first); 
         ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1203:9: note: 
     in instantiation of function template specialization 'std::__1::vector<std::__1::unique_ptr<A, 
     std::__1::default_delete<A> >, std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > > 
     >::__construct_at_end<std::__1::unique_ptr<A, std::__1::default_delete<A> > *>' requested here 
     __construct_at_end(__x.__begin_, __x.__end_); 
     ^
vector_unique.cpp:15:8: note: in instantiation of member function 'std::__1::vector<std::__1::unique_ptr<A, 
     std::__1::default_delete<A> >, std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > > 
     >::vector' requested here 
     class Obj { 
      ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1572:18: note: 
     (skipping 2 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all) 
      {__a.construct(__p, _VSTD::forward<_Args>(__args)...);} 
       ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1535:17: note: 
     in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<Obj> 
     >::construct<Obj, const Obj &>' requested here 
       construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1)); 
       ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:874:21: note: 
     in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<Obj> 
     >::__construct_backward<Obj *>' requested here 
    __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_); 
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1621:5: note: 
     in instantiation of member function 'std::__1::vector<Obj, std::__1::allocator<Obj> 
     >::__swap_out_circular_buffer' requested here 
    __swap_out_circular_buffer(__v); 
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1639:9: note: 
     in instantiation of function template specialization 'std::__1::vector<Obj, std::__1::allocator<Obj> 
     >::__emplace_back_slow_path<__gmp_expr<mpq_t, mpq_t> &, std::__1::vector<std::__1::unique_ptr<A, 
     std::__1::default_delete<A> >, std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > > > >' 
     requested here 
     __emplace_back_slow_path(_VSTD::forward<_Args>(__args)...); 
     ^
vector_unique.cpp:40:11: note: in instantiation of function template specialization 'std::__1::vector<Obj, 
     std::__1::allocator<Obj> >::emplace_back<__gmp_expr<mpq_t, mpq_t> &, std::__1::vector<std::__1::unique_ptr<A, 
     std::__1::default_delete<A> >, std::__1::allocator<std::__1::unique_ptr<A, std::__1::default_delete<A> > > > >' 
     requested here 
         result.emplace_back(rational, std::move(abstractObjectsForConstructor)); 
          ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2515:31: note: 
     copy constructor is implicitly deleted because 'unique_ptr<A, std::__1::default_delete<A> >' has a 
     user-declared move constructor 
    _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT 
          ^
1 error generated. 
+1

Показывает полное сообщение об ошибке. Каждый главный компилятор перечисляет номер строки с сообщением об ошибке. Сообщите нам, какая строка вашего кода соответствует номеру строки в ошибке. –

ответ

-3

[неправильно, смотрите ниже]

Проблема с определением конструктора Obj. Второй аргумент передается по значению, что приводит к созданию копии. Тот факт, что вы используете std :: move в списке инициализаторов, не изменяет этот факт.

Средство должно использовать ссылку rvalue для второго аргумента конструктора Obj.

+0

Я не слишком уверен в этом - если я объявлю аргумент конструктора «по значению» и передать его в rvalue-reference. Я надеюсь, что он будет создан и не скопирован, как вы говорите. Рассмотрим текущую директиву о передаче «std :: string' по значению - она ​​будет копироваться, когда это необходимо (если вы передаете значение lvalue), и создайте перемещение, когда вы проходите временное. – Alejandro

+0

Вы правы. Я записал свою запись как ошибочную. –

8

Culprit is mpq_class. С помощью простой фиктивной версии компилирует нормально (я закомментирована заголовки для ГМП):

struct mpq_class { 
    mpq_class() {} 
    mpq_class(int, int); 
}; 

Однако, когда вы делаете этот класс не движимое:

struct mpq_class { 
    mpq_class() {} 
    mpq_class(int, int); 
    mpq_class(const mpq_class &) {} 
    mpq_class(mpq_class &&) = delete; 

    mpq_class &operator=(const mpq_class &) {return *this;} 
}; 

Ваша проблема возвращается.

Так что, если выпустить mpq_class не подвижен, то Obj не движимый либо и использование emplace_back неявно генерирует код для копирования Obj в случае переселения, который не смогло собрать, потому что std::unique_ptr<A> не копируемая.