I wish to create a wrapper around std::make_pair that takes a single argument and uses that argument to make the first and second members of the pair. Furthermore, I wish to take advantage of move semantics.
Naively, we might write (ignoring return types for clarity),
template <typename T>
void foo(T&& t)
{
std::make_pair(std::forward<T>(t),
std::forward<T>(t));
}
but this is unlikely to do what we want.
What we want is:
- In the case where foo is called with a (const) lvalue reference argument, we should pass that (const) reference on to std::make_pair unmodified for both arguments.
- In the case where foo is called with an rvalue reference argument, we should duplicate the referenced object, then call std::make_pair with the original rvalue reference as well as an rvalue reference to the newly created object.
What I've come up with so far is:
template <typename T>
T forward_or_duplicate(T t)
{
return t;
}
template <typename T>
void foo(T&& t)
{
std::make_pair(std::forward<T>(t),
forward_or_duplicate<T>(t));
}
But I'm reasonably sure it's wrong.
So, questions:
Does this work? I suspect not in that if foo() is called with an rvalue reference then T's move constructor (if it exists) will be called when constructing the T passed by value to forward_or_duplicate(), thus destroying t.
Even if it does work, is it optimal? Again, I suspect not in that T's copy constructor will be called when returning t from forward_or_duplicate().
This seems like a common problem. Is there an idiomatic solution?
std::make_pair(t, std::forward<T>(t))if the ordering between parameter evaluation was defined (unfortunately, it isn't). - Cameronforward_or_duplicate. - T.C.make_pairtakes arguments by reference, so the move happens inside it, and the copy happens before you entermake_pair. - T.C.