Push_back vs emplace_back with mutable

The following code does not execute for push_back and succeeds for emplace_back :

 #include <vector> volatile int x = 0; int main() { std::vector<int> vec; vec.emplace_back(x); vec.push_back(x); // error: no matching function for call to 'std::vector<int>::push_back(volatile int&)' } 

I understand that push_back fails because it accepts the link and tries to drop volatile implicitly from that link.

However, emplace_back also accepts a link (rvalue-reference links). Why is this considered differently?

+4
source share
1 answer

This is due to how they are defined in the C ++ 11 standard. Clause 23.3.6.1 indicates their signature:

 template <class... Args> void emplace_back(Args&&... args); void push_back(const T& x); void push_back(T&& x); 

As long as the available overloads for push_back() do not have volatile qualifications, the template argument to the emplace_back() function can be associated with lvalues ​​with any cv -qualification.

However, emplace_back also accepts a link (rvalue-reference links). Why is this happening differently?

Yes, since emplace_back() is a function template, and type inference prints Args as a package of arguments of length one, whose only element is of type int volatile& (see clause 14.8.2.1/3).

The overloads of push_back() , on the other hand, are regular member functions of the template of the std::vector<> class, and when they are called, no type inference occurs. Since references to non- volatile cannot communicate with objects qualified as volatile (see Section 8.5.3 / 4-5), the compiler will not be able to resolve the call.

+8
source

All Articles