简体   繁体   中英

Why does this std::vector::emplace_back fail?

I'm coming across a compiler error that says:

attempting to reference a deleted function

#include <iostream>
#include <vector>

template <typename T>
struct Container
{
    Container() = default;
    Container(const Container& other) = delete;
    Container(T* ptr) : ptr(ptr) {}
    T* ptr;
    ~Container() { delete ptr; }

};

struct Foo { Foo(int a, int b) {} };

int main()
{
    std::vector<Container<Foo>> myvector;
    myvector.push_back(new Foo(1, 2)); // I understand why this doesn't work.
    myvector.emplace_back((new Foo(1, 2))); // I don't understand why this fails

}

I understand why it says attempting to reference a deleted constructor when I do std::vector::push_back() , because this does a copy and needs to call the copy constructor , which I deleted.

But std::vector::emplace_back() is supposed to take the constructor arguments of the type it holds. When I emplace back, I give it a pointer to a Foo , and this should be forwarded to the Container::Container(T* ptr) constructor.

What am I missing?

Declaring a User-Defined copy constructor will not define an implicit move constructor ; T must either have a copy constructor or a move constructor to push_back or emplace_back* an object into a std::vector<T> .

From the docs , see the requirements on T to instantiate a std::vector<T> . (No restriction here, read on) .. emphasis mine

The requirements that are imposed on the elements depend on the actual operations performed on the container . Generally, it is required that element type meets the requirements of Erasable, but many member functions impose stricter requirements . This container (but not its members) can be instantiated with an incomplete element type if the allocator satisfies the allocator completeness requirements.

From std::vector<...>::push_back :

Type requirements

  • T must meet the requirements of CopyInsertable in order to use overload (1).
  • T must meet the requirements of MoveInsertable in order to use overload (2).

From std::vector<...>::emplace_back :

Type requirements

  • T (the container's element type) must meet the requirements of MoveInsertable and EmplaceConstructible .

For emplace_back here, your code would fulfill the EmplaceConstructible criteria, however, because reallcations can happen, you must equally fulfill MoveInsertable .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM