For the built-in types the prefix +
plays the role of “make a copy”:
void foo( char&& ) {}
void bar( double*&& ) {}
auto main() -> int
{
char x{};
foo( +x );
double* p{};
bar( +p );
}
Still, it would probably be confusing to readers of the code if you applied prefix +
to some other type, and a general prefix operator+
template might end up in conflict with some class' own prefix operator+
.
So, I suggest using the now apparent naming convention for makers, namely a make
prefix.
Then it can look like this:
template< class Type >
auto make_copy( Type const& o ) -> Type { return o; }
Your first proposed solution,
template<typename T> auto mk_copy(T val){return val;}
suffers from potentially copying the value twice: first copying to the by-value argument, and then copying to the function result.
This is not a problem for a movable type such as a standard library container, because the return type copying will reduce to a move. But it can be a problem for largish non-movable type, as can occur in legacy code.
The second proposed solution,
template<typename T> auto mk_copy(T&& val){return std::forward<T>(val);}
takes the argument by forwarding reference (a.k.a. universal reference), and then deduces the return type from a re-creation of the argument type. The return type will always be a non-reference, since that's what plain auto
deduces, so this is technically correct. But it's needlessly complicated.