2010-11-28 2 views
17

Рассмотрим следующий код:C++ 11 вектор push_back неоднозначным

#include <vector> 

struct S { int a; double b; }; 

int main() 
{ 
    std::vector<S> v; 
    v.push_back({3, 4.5}); 
} 

г ++ 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>] 

Это должно быть неоднозначным в соответствии с Стандарт, или это просто проблема с g ++?

Я знаю, что это может быть решена путем записи в типе S явно:

v.push_back(S{3, 4.5}); 

но имя типа S может быть долгим, поэтому я предпочел бы не делать этого ...

+0

Я предполагаю, что ваш компилятор не имеет всех новых реализаций ссылок (move или &&) и правила, установленные в какой форме предпочитают использовать для этого временного (например, должен взять подвижный, так как ваш объект является временным) – David 2010-11-29 00:58:37

ответ

4

С самым последним проектом (n3225) ваш код на самом деле неоднозначен. Кандидаты, которые находятся в векторе будет

void push_back(const S& x); 
void push_back(S&& x); 

Вопрос: Является ли список инициализация из const S&лучше/хуже последовательности преобразования чем-списка инициализации S&&? Разрешение перегрузки будет производить как конверсии пользовательские последовательности преобразования. Это означает, что они не сопоставимы, потому что нет правила, которое может это сделать.

Это обрабатывается core issue #1079. Если эта проблема будет принята, предполагается, что ваш код вызывает второго кандидата. Кстати, Jason Merril является разработчиком GCC :)

6

Нужно ли S быть POD? Если нет, определите конструктор, и он должен работать.

struct S 
{ 
    int a; 
    double b; 

public: 

    S(int a, double b) : a(a), b(b) {} 
}; 

Кроме того, v.push_back({3, 4.5}), вероятно, менее эффективен, чем v.emplace_back(3, 4.5).


Update: Пахнет ошибка компилятора. Он отлично работает с g ++ 4.6.0 20101025 (экспериментальный).

+3

Хотя полезно, не совсем то, что спрашивает OP? Мне также любопытно, что там происходит - почему один вариант однозначен в том, что он является lvalue/rvalue, а другой нет, хотя они оба, ну, временные. – Kos 2010-11-28 22:54:10

Смежные вопросы