push_back vs emplace_back with volatile

Sta*_*ked 4 c++

以下代码失败push_back并成功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&)'
}
Run Code Online (Sandbox Code Playgroud)

我理解push_backfailes因为它需要一个引用并试图volatile从该引用隐式地抛弃限定符.

但是,emplace_back 需要引用(rvalue-references是引用).为什么区别对待?

And*_*owl 8

这是因为它们在C++ 11标准中的定义方式.第23.3.6.1段规定了其签字:

template <class... Args> void emplace_back(Args&&... args);
void push_back(const T& x);
void push_back(T&& x);
Run Code Online (Sandbox Code Playgroud)

虽然可用重载的参数push_back()没有任何volatile限定,但emplace_back()函数模板的参数可以使用任何cv限定条件绑定到左值.

但是,emplace_back也需要引用(rvalue-references是引用).为什么它的处理方式不同?

是的,因为emplace_back()是函数模板,类型推导将推断Args为长度为1的参数包,其唯一元素具有类型int volatile&(参见第14.8.2.1/3节).

push_back()另一方面,重载是std::vector<>类模板的常规成员函数,并且在调用它们时不会进行类型推导.由于对non的引用volatile不能绑定到限定为的对象volatile(参见第8.5.3/4-5段),编译器将无法解析该调用.