Reputation: 1498
Under the C++11 standard, is the following pair guaranteed to be moved into the function?
//objects available: key, value
//corresponding type available: pairtype
//function available: void foo(pairtype pair); copies the pair by default
foo({std::move(key),std::move(value)}); //pair moved?
or do I have to do the move myself?
foo(std::move(pairtype(std::move(key),std::move(value))); //needed?
Upvotes: 2
Views: 398
Reputation: 126452
Initializer lists are not expressions, so they do not have a type and they do not yield a value. This means that the following:
{std::move(key),std::move(value)}
Does not in itself create a pair. Initializer lists are just a syntactic construct used for initialization, and in this case the function parameter will be constructed by directly invoking the constructor of pairtype
with std::move(key)
and std::move(value)
as arguments.
There is no creation of temporaries involved - the only thing to be aware of is that explicit
constructors will not be considered when performing list-initialization (for instance, this would not work with an instance of std::tuple<>
).
Which means that the invocation of foo
we just discussed, i.e.:
foo({std::move(key),std::move(value)}
Is technically different from this invocation:
foo(std::move(pairtype(std::move(key),std::move(value)))
Here, you are intentionally creating a temporary and moving it into the function parameter (the compiler may then elide this move per 12.8/31, but this is another story).
Notice, that the call to std::move()
here is superfluous, since temporaries are rvalues. The function parameter will be move-constructed from the temporary object anyway. You can therefore write:
foo(pairtype(std::move(key),std::move(value)))
Notice, that pairtype
will be an instance of the std::pair<>
class template, which means you will have to specify template arguments manually. To avoid this, you can use std::make_pair()
:
foo(std::make_pair(std::move(key),std::move(value)))
Upvotes: 8