Search

VC10 STL: emplace functions are not implemented for more than 1 parameter by Dávid Róbert

Closed
as Fixed Help for as Fixed

4
0
Sign in
to vote
Type: Bug
ID: 645116
Opened: 2/18/2011 6:38:14 AM
Access Restriction: Public
0
Workaround(s)
4
User(s) can reproduce this bug
In Visual Studio 2010 (also in SP1 beta), the new emplace functions of containers are not implemented for more than one parameter.

I will use the std::vector<Val>::empace_back(..) function from now on, but all applies for all STL conatiners, and also other emplace-type member functions.

MSDN documentation (http://msdn.microsoft.com/en-us/library/dd647620.aspx) writes: Adds an element constructed in place to the end of the vector. Basically, this is something like what std::make_shared is doing, in the meanwhile it is doing some other magic (creating the shared_ptr in make_shared's case, reallocating the vector if necessary in emplace_back's case), it is calling the element type's constructor, forwarding its parameters.

According to MSDN, there is only one implementation of emplace_back, what is taking an rvalue reference of the contained type, and it will call the contained type's move-constructor (and reallocate, move the already contained elements before, if needed). But this means emplace_back is basically equivalent to push_back(Val&&), and this is what actually is in the <vector> header, emplace_back(Val&&) just calling push_back(Val&&).

There is also an undocumented(!) version of template<class T> emplace_back(T&&), implemented right after emplace_back(Val&&) in the <vector> header, and it is actually doing what the documentation is doing: after doing the necessary magic necessary for the vector to hold the extra element (reallocation, moving current elements around), it calls the element type's constructor, forwarding the parameter.

The problem is, that according to the standard, this is a variadic template function, there is no limit on the number of parameters, and VC10 compiler does not support variadic templates. "10 is not quite infinity", but in most cases, more than enough. So std::make_shared does a workaround for the lack of variadic template support, implementing it only for up to 10 parameters.

The workaround for the lack of multi-parameter emplace support involves creating a temporary object, passing it to emplace_back, then destroying the temporary, so there is an extra move constructor and destructor call in the process, making this a performance problem.
Details (expand)

Visual Studio/Silverlight/Tooling version

Visual Studio 2010 SP1 Beta

What category (if any) best represents this feedback?

Compatibility

Steps to reproduce

Compile the following code:

#include <iostream>
#include <vector>

struct Foo {
    Foo(Foo&&)    { std::cout << "move ctr" << std::endl; }
    Foo(int)     { std::cout << "1p ctr" << std::endl; }
    Foo(int, int) { std::cout << "2p ctr" << std::endl; }
    ~Foo()        { std::cout << "dstrctr" << std::endl; }
};

int __cdecl main(){
    std::vector<Foo> bar;
    bar.reserve(3); //to avoid intermediate moves
    std::cout << "emplace call with 1 param" << std::endl;
    bar.emplace_back(5);
    std::cout << "emplace call with 2 param" << std::endl;
    bar.emplace_back(5,6);
    std::cout << "emplace call with 2 param workaround" << std::endl;
    bar.emplace_back(Foo(5,6));
    std::cout << "After emplace calls:" << std::endl;
}

Comparing the results of the two 2 parameter versions show why this is a performance problem.

Product Language

English

Operating System

Windows 7

Operating System Language

English

Actual results

The second emplace_back call does not compile with:
error C2660: 'std::vector<_Ty>::emplace_back' : function does not take 2 arguments.

Expected results

The sample should compile. The expected result printed on the standard output:

emplace call with 1 param
1p ctr
emplace call with 2 param
2p ctr
emplace call with 2 param workaround
2p ctr
move ctr
dstrctr
After emplace calls:
dstrctr
dstrctr
dstrctr
File Attachments
0 attachments
Sign in to post a comment.
Posted by Microsoft on 6/13/2011 at 4:03 PM
Hi,

Thanks for reporting this bug - actually, partially implemented feature. We've fully implemented it, and this will be available in VC11. All containers will have emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after() as specified by the Standard. Because we're generating many more "fake variadic" overloads, we've changed our scheme slightly. By default, up to 5 arguments will be supported, but this can be increased to 10 with a macro (at the cost of longer compile times and greater PCH memory consumption).

If you have any further questions, feel free to E-mail me at stl@microsoft.com .

Stephan T. Lavavej
Visual C++ Libraries Developer
Posted by Microsoft on 2/20/2011 at 11:17 PM
Thank you for submitting feedback on Visual Studio 2010 and .NET Framework. Your issue has been routed to the appropriate VS development team for review. We will contact you if we require any additional information.
Posted by Microsoft on 2/18/2011 at 6:59 AM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.