push_back vs emplace_back with a volatile
c++
Solution
That is because of how they are defined in the C++11 Standard. Paragraph 23.3.6.1 specifies their signature:
template <class... Args> void emplace_back(Args&&... args);
void push_back(const T& x);
void push_back(T&& x);
While the parameters of the available overloads of `push_back()` do not have any `volatile` qualification, the argument of the `emplace_back()` function template can bind to lvalues with any `cv`-qualification.
However, emplace_back also takes a reference (rvalue-references are references). Why is it ttreated differently?
Yes, because `emplace_back()` is a function template, and type deduction will infer `Args` to be an argument pack of length one, whose only element has type `int volatile&` (see Paragraph 14.8.2.1/3).
The overloads of `push_back()`, on the other hand, are regular member functions of the `std::vector<>` class template, and there is no type deduction going on when invoking them. Since references to non-`volatile` cannot bind to objects qualified as `volatile` (see Paragraph 8.5.3/4-5), the compiler won't be able to resolve the call.
Problem
The following code fails 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` failes because it takes a reference and tries to cast away `volatile` qualifier implicitly from that reference. However, `emplace_back` also takes a reference (rvalue-references are references). Why is it treated differently?