user2736667
user2736667

Reputation: 371

Compiler error with vector of deque of unique_ptr

The following code fails to compile on gcc 5.3 with compiler error complaining that the copy constructor of the unique_ptr is somehow invoked. Can someone explain why this happens?

#include <iostream>
#include <memory>
#include <deque>

using Foo = std::deque<std::unique_ptr<int>>;                                   


void foo() {                                                                    
  std::vector<Foo> a;                                                           
  a.emplace_back();   // this fails to compile                                                             
}

The key line in the compiler error is:

gcc-4.9.2/include/c++/4.9.2/bits/stl_construct.h:75:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’ { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

Upvotes: 7

Views: 593

Answers (1)

T.C.
T.C.

Reputation: 137320

  • vector::emplace_back needs to handle reallocation.
  • on vector reallocation, the existing elements are moved if either

    • they cannot be copied (as determined by std::is_copy_constructible); or
    • their move constructor is noexcept.

    otherwise they are copied. This is to maintain the strong exception safety guarantee.

  • std::deque<std::unique_ptr<int>>'s move constructor is not noexcept (depending on the implementation, it may need to allocate memory).
  • std::deque<std::unique_ptr<int>> can be copied according to std::is_copy_constructible, because that only checks if there is a constructor with the right signature, not whether the body of said constructor will actually compile.
  • vector::emplace_back therefore attempts to copy it.
  • the compiler blows up.

Upvotes: 6

Related Questions