Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing parameter pack to emplace stl function cause compilation bug

According to the definition of emplace_back, void emplace_back (Args&&... args); is a variadic template function. So, I wrote the following:

#include <vector>

int main()
{
  std::vector<int> myvector2(10,0);
  myvector2.emplace_back(1,2,3,4,5,6);
}

The compiler complains:

g++ -std=c++0x stlstudy.cc
‘
Internal compiler error: Error reporting routines re-entered.
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.7/README.Bugs> for instructions.
Preprocessed source stored into /tmp/cc7q32tE.out file, please attach this to your bugreport.

And the OS alerts:

Sorry, Ubuntu 13.04 has experienced an internal error.

The /tmp/cc7q32tE.out filen is too long to post it here and maybe it will not help. Am I doing something wrong or is compilation bug? I don't get it.

After the comments and the bug report: jrok gives a very good explanation about why this happens. I used gcc 4.7, I reported the bug and I got the following response:

Jonathan W***** <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
      Known to work|                            |4.8.0

--- Comment #1 from Jonathan W***** <redi at gcc dot gnu.org> ---
Seems to be fixed for 4.8 already.
like image 591
Avraam Mavridis Avatar asked May 23 '13 13:05

Avraam Mavridis


1 Answers

Internal compiler error is not your fault. Compilers are supposed to give a meaningful diagnostic in case of ill-formed input, not just crash on you.

However, the number and types of arguments of emplace_back must match one of the constructors of vector's value type. You have a vector of ints, so you can pass at most one argument that either has a matching type or is implicitly convertible to value_type. (You could leave argument list empty - that would construct the object using default constructor).

std::vector<int> v;
v.emplace_back(1);   // ok
v.emplace_back(1.0); // ok
v.emplace_back(1, 2); // not ok, there's no constructor for `int` that takes two ints

The purpose of emplace_back isn't to push multiple elements in the same statement (I got an impression that this is what you expected it to do - I thought the same a while ago) but to construct an element in place, forwarding the arguments to the constructor and avoiding copies).

Gcc 4.8. does error out, although the error message isn't particulalry helpul.

like image 67
jrok Avatar answered Oct 18 '22 22:10

jrok