template<class T>
std::remove_cv_t<T> copy(T& t) {
return t;
}
template<class T>
void copy(T&&)=delete; // block rvalue copy
template<class T, size_t N>
void copy(T(&)[N]) = delete; // we can implement this if we want: see below
will copy any lvalue. On rvalues and non-copyable types (like arrays) it will fail to match or compile.
template<class T>
std::decay_t<T> copy_even_if_rvalue(T&& t) {
return std::forward<T>(t);
}
namespace details {
template<class T, size_t N, size_t...Is>
std::array<T, N> copy_even_if_rvalue(T(&arr)[N], std::index_sequence<Is...>)
{
return {{arr[Is]...}};
}
}
template<class T, size_t N>
std::array<T, N> copy_even_if_rvalue(T(&arr)[N]) {
return details::copy_even_if_rvalue(arr, std::make_index_sequence<N>{} );
}
template<class T, size_t N>
std::array<T, N> copy_even_if_rvalue(T(&&arr)[N]) {
return copy_even_if_rvalue(arr); // forward to lvalue version
}
will copy both rvalues and lvalues. Usually copy
is a smarter operation than copy_even_if_rvalue
in my opinion.
copy_even_if_rvalue
will convert raw C arrays into std::array
s, because that is about the only sensible way to copy them. An =delete
overload would be the other reasonable option.