C++11:显式复制值以用作右值引用的最短方法
C++11: shortest way to explicitly copy a value to use as an rvalue reference
我有一个功能
class A { <has copy and move constructors > };
void f(A &&a) { ... }
我想用变量 x
调用函数 f,但我想 运行 f
在 x
的副本上,而不是 x
本身。为什么我不能做这样的事情?
f(copy(x));
而是必须做
f(A(x));
有没有类似我上面描述的copy
函数的东西?
注意:请不要告诉我添加执行复制的重载 f
,我想要一些不需要重载并且是显式的(即 copy
明确说明到reader复制在这里完成)
这个呢?
template <typename T>
T copy(T t) {return t;}
当您按值传递 t
并进行后续移动时,复制完成。
http://coliru.stacked-crooked.com/a/cbc1a161f65a022b
如果你可以修改你的函数为:
void func(A) {}
那你就可以了
int main() {
A a;
func(a); //copies
func(std::move(a)); //moves
return 0;
}
没有任何额外的构造函数调用。
使用拷贝构造函数怎么样?
你可以这样做:
A::A(const A &obj){
//copy constructor here
}
// in external header
void copy(const A &obj){
return A::A(obj);
}
玩得开心
女友
根据建议编辑
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
将复制任何左值。在右值和不可复制类型(如数组)上,它将无法匹配或编译。
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
}
将同时复制右值和左值。在我看来,通常 copy
比 copy_even_if_rvalue
更聪明。
copy_even_if_rvalue
会将原始 C 数组转换为 std::array
s,因为这是复制它们的唯一合理方法。 =delete
重载是另一个合理的选择。
最短的方法就是f(A{x})
如果由于某种原因类型 A
太长或太丑而无法输入,那么这仍然比在全局范围内定义一个新函数要短:
f(std::decay_t<decltype(x)>(x));
或者没有 C++14 别名模板:
f(typename std::decay<decltype(x)>::type(x));
我有一个功能
class A { <has copy and move constructors > };
void f(A &&a) { ... }
我想用变量 x
调用函数 f,但我想 运行 f
在 x
的副本上,而不是 x
本身。为什么我不能做这样的事情?
f(copy(x));
而是必须做
f(A(x));
有没有类似我上面描述的copy
函数的东西?
注意:请不要告诉我添加执行复制的重载 f
,我想要一些不需要重载并且是显式的(即 copy
明确说明到reader复制在这里完成)
这个呢?
template <typename T>
T copy(T t) {return t;}
当您按值传递 t
并进行后续移动时,复制完成。
http://coliru.stacked-crooked.com/a/cbc1a161f65a022b
如果你可以修改你的函数为:
void func(A) {}
那你就可以了
int main() {
A a;
func(a); //copies
func(std::move(a)); //moves
return 0;
}
没有任何额外的构造函数调用。
使用拷贝构造函数怎么样? 你可以这样做:
A::A(const A &obj){
//copy constructor here
}
// in external header
void copy(const A &obj){
return A::A(obj);
}
玩得开心
女友
根据建议编辑
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
将复制任何左值。在右值和不可复制类型(如数组)上,它将无法匹配或编译。
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
}
将同时复制右值和左值。在我看来,通常 copy
比 copy_even_if_rvalue
更聪明。
copy_even_if_rvalue
会将原始 C 数组转换为 std::array
s,因为这是复制它们的唯一合理方法。 =delete
重载是另一个合理的选择。
最短的方法就是f(A{x})
如果由于某种原因类型 A
太长或太丑而无法输入,那么这仍然比在全局范围内定义一个新函数要短:
f(std::decay_t<decltype(x)>(x));
或者没有 C++14 别名模板:
f(typename std::decay<decltype(x)>::type(x));