C++ 11向量push_back模糊不清

HC4*_*ica 17 c++ vector c++11

请考虑以下代码:

#include <vector>

struct S { int a; double b; };

int main()
{
    std::vector<S> v;
    v.push_back({3, 4.5});
}
Run Code Online (Sandbox Code Playgroud)

g ++ 4.4抱怨对push_back()的调用不明确:

error: call of overloaded ‘push_back(<brace-enclosed initializer list>)’ is ambiguous
note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = S, _Alloc = std::allocator<S>]
note:                 void std::vector<_Tp, _Alloc>::push_back(_Tp&&) [with _Tp = S, _Alloc = std::allocator<S>]
Run Code Online (Sandbox Code Playgroud)

根据标准,这应该是模棱两可的,还是这只是g ++的一个问题?

我知道可以通过明确写出S的类型来解决它:

v.push_back(S{3, 4.5});
Run Code Online (Sandbox Code Playgroud)

但是S的类型名称可能很长,所以我宁愿不这样做......

fre*_*low 6

是否S必须是一个POD?如果没有,定义一个构造函数,它应该工作.

struct S
{
    int a;
    double b;

public:

    S(int a, double b) : a(a), b(b) {}
};
Run Code Online (Sandbox Code Playgroud)

而且,v.push_back({3, 4.5})可能效率低于v.emplace_back(3, 4.5).


更新:闻起来像编译器错误.它与g ++ 4.6.0 20101025(实验性)完美配合.

  • 虽然有用,但不是OP的要求吗?我也很好奇那里发生了什么 - 为什么一个变体是一个关于左值/左值的另一个变体而另一个变量是不是,虽然它们都是临时的. (3认同)
  • @Kos:临时的人有不同的类型.`{3,4.5}`是`std :: initializer_list <double>`,而`S {3,4.5}`是`S`.也许这与`a`是`int`而不是`double`这一事实有关?老实说,我不知道. (2认同)
  • @FredOverflow:我认为{3,4.5}的类型不是std :: initializer_list <double> - 这意味着{}中每个对象的类型都被强制为同一个东西,不可能是因为{}语法适用于具有广泛不同成员类型的结构. (2认同)

Joh*_*itb 4

在最新的草案(n3225)中,您的代码实际上是不明确的。向量中的候选者将是

void push_back(const S& x);
void push_back(S&& x);
Run Code Online (Sandbox Code Playgroud)

问题是: a 的列表初始化是否比a列表初始化更好/更差的转换序列?重载解析将使这两种转换都成为用户定义的转换序列。这意味着它们不具有可比性,因为没有规则可以这样做。const S&S&&

这是由核心问题 #1079处理的。如果该问题被接受,则目的是您的代码调用第二个候选者。顺便说一句,Jason Merril 是 GCC 开发人员:)