Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 vector push_back ambiguous

Tags:

c++

c++11

vector

Consider the following code:

#include <vector>

struct S { int a; double b; };

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

g++ 4.4 complains that the call to push_back() is ambiguous:

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

Is this supposed to be ambiguous according to the Standard, or is this just an issue with g++?

I know it can be resolved by writing in the type of S explicitly:

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

but the type name of S may be long, so I'd rather not do that...

like image 460
HighCommander4 Avatar asked Nov 28 '10 22:11

HighCommander4


People also ask

What does Push_back do in a vector?

vector::push_back() push_back() function is used to push elements into a vector from the back. The new value is inserted into the vector at the end, after the current last element and the container size is increased by 1.

What is the time complexity of Push_back in vector?

push_back(): Inserts a new element at the end of the vector. Its time complexity is O(1).

Which is better Push_back or Emplace_back?

The difference in the efficiency of push_back and emplace_back depends on the type of our vector. If the vector is a built-in type, there is no difference between the efficiency of push_back and emplace_back. If the vector type is class or struct, emplace_back is more efficient than push_back.

What does Push_back mean?

The push_back() function is used to insert an element at the end of a vector. This function is available in the <vector> header file.


2 Answers

Does S have to be a POD? If not, define a constructor, and it should work.

struct S
{
    int a;
    double b;

public:

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

Also, v.push_back({3, 4.5}) is probably less efficient than v.emplace_back(3, 4.5).


Update: Smells like a compiler bug. It works perfectly well with g++ 4.6.0 20101025 (experimental).

like image 56
fredoverflow Avatar answered Sep 24 '22 06:09

fredoverflow


With the most recent draft (n3225), your code is in fact ambiguous. The candidates that are in vector will be

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

The question is: Is a list-initialization of a const S& a better/worse conversion sequence than a list-initialization of a S&&? Overload resolution will make both conversions user defined conversion sequences. This means they are not comparable because there is no rule that can do so.

This is handled by core issue #1079. If that issue gets accepted, the intention is that your code calls the second candidate. Incidentally, Jason Merril is a GCC developer :)

like image 43
Johannes Schaub - litb Avatar answered Sep 24 '22 06:09

Johannes Schaub - litb