1

I think that using emplace(c.end(),_1) would be same as emplace_back(_1) But I am not understanding why the language designers gave two functions instead of one. I am assuming I am missing some information.

So what is it that differentiate emplace(c.end(),_1) from emplace_back(_1) ?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Ajeet Ganga
  • 8,353
  • 10
  • 56
  • 79

3 Answers3

5

The big difference is the requirements on the container's value_type is lessened for vector::emplace_back and deque::emplace_back compared to emplace.

Speaking for vector and deque only:

In addition to EmplaceConstructible from args;

emplace requires MoveInsertable and MoveAssignable, whereas

emplace_back only requires MoveInsertable.

For most allocators, including std::allocator, MoveInsertable is the same as MoveConstructible.

So if you have a type that you want to put into a vector or deque, and it is MoveConstructible, but not MoveAssignable, emplace_back is your friend. It is also likely to be slightly faster, and have slightly smaller code size, but that is a quality-of-implementation issue (not guaranteed by the standard). And the difference is likely to be smaller than you will notice (unless measuring carefully).

For example, given:

#include <vector>

struct A
{
    A() = default;
    A(A&&) = default;
    A& operator=(A&&) = delete;
};

This compiles:

int main()
{
    std::vector<A> v;
    v.emplace_back();
}

But this does not:

int main()
{
    std::vector<A> v;
    v.emplace(v.end()); //  error A is not MoveAssignable
}

However if I changed:

    A& operator=(A&&) = delete;

to:

    A& operator=(A&&) = default;

then both examples would compile (and run fine).

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
2

Depending on the data structure, it may be possible to make emplace_back faster than emplace(c.end(), _1). For example using std::vector, emplace_back would not have to check which (if any) elements need to be shifted, making emplace_back slightly faster.

David Brown
  • 13,336
  • 4
  • 38
  • 55
1

Yeah, they're equivalent in that case.

emplace is more general as it works not just at the end; emplace_back is convenient because you don't have to write c.end().

There may also be benefits to the implementation — recall that emplace doesn't know that the iterator you provided to it was the end iterator.

That's it.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Interesting case where [this best practice](http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197) was not followed. Same for `insert()` and `push_back()` I guess. – Andy Prowl Feb 16 '13 at 21:20
  • Bloody standard. Container operation requirements are defined in such a way that I can't find a way to prove this equivalence concisely and formally. Pfft. – Lightness Races in Orbit Feb 16 '13 at 21:22