C++ 用右值交换
假设我想要在右值上工作的C++ 用右值交换,c++,swap,move-semantics,rvalue-reference,C++,Swap,Move Semantics,Rvalue Reference,假设我想要在右值上工作的swap,并且不想为右值/左值引用的所有组合编写4个版本(右值/右值版本有点毫无意义,但不会造成伤害)。我想到了这个: template <typename A, typename B> struct is_same_no_ref : std::is_same< typename std::remove_reference<A>::type, typename std::remove_reference
swap
,并且不想为右值/左值引用的所有组合编写4个版本(右值/右值版本有点毫无意义,但不会造成伤害)。我想到了这个:
template <typename A, typename B>
struct is_same_no_ref
: std::is_same<
typename std::remove_reference<A>::type,
typename std::remove_reference<B>::type
>
{};
template <typename A, typename B,
typename = typename std::enable_if<is_same_no_ref<A, B>::value>::type
>
inline void my_swap(A&& a, B&& b) {
typename std::remove_reference<A>::type t = std::move(a);
a = std::move(b);
b = std::move(t);
}
模板
结构相同\u无\u参考
:std::是否相同<
typename std::remove_reference::type,
typename std::remove_reference::type
>
{};
模板
内联作废我的交换(A&&A,B&&B){
typename std::remove_reference::type t=std::move(a);
a=标准::移动(b);
b=标准::移动(t);
}
这似乎和预期的一样。这样行吗?还是我遗漏了一些重要的东西,这些东西以后会让我受苦?虽然我认为您的实现中没有固有的概念缺陷,但我想提出三点建议 (注意:这里我将把交换右值的概念的实现称为
交换右值
)
从模板推断中排除常量类型
- 怎么做?
template <typename A, typename B>
struct is_same_no_ref
: std::is_same<
typename std::remove_reference<A>::type,
typename std::remove_reference<B>::type
>
{};
诱导编译器标记与内部实现细节有关的错误,这不是非常用户友好的
将启用条件移动到返回类型声明
- 怎么做?
template<typename A, typename B, typename = typename std::enable_if<...>::type>
inline void swap_rvalues(A&& a, B&& b);
它可以编译,尽管它显然不应该A
和B
甚至不相关,它们只是碰巧可以在引用另一个的情况下构造
重用代码[aka]
- 怎么做?
交换右值实现
- 为什么?
为什么†<代码>标准::交换
一旦给右值一个名称,就已经提供了预期的行为,那么为什么不重用它呢
结论
交换值的最终实现如下所示
template <typename A, typename B>
inline typename std::enable_if<
is_same_no_ref<A, B>::value &&
!std::is_const<typename std::remove_reference<A>::type>::value &&
!std::is_const<typename std::remove_reference<B>::type>::value
>::type
swap_rvalues(A&& a, B&& b) {
std::swap(a, b);
}
模板
内联typename std::启用\u如果<
值是否相同&&
!std::is_Uconst::value&&
!std::is_const::value
>::类型
交换值(A和A、B和B){
标准:交换(a,b);
}
脚注
†“重新发明方向盘”是指复制先前已由他人创建或优化的基本方法
——swap——事实上,在真实场景中最好称为swap
。为什么不呢:模板无效交换(a&&a,B&&B){auto t=move(a);a=move(B);B=move(t)}
?@MM。这是不太对称的。我确实意识到,只有当A
和B
可以“相互移动”时,它才会起作用,但仍然如此。我相信你的意思是是相同的\u否\u参考
而不是标准::是相同的\u否\u参考
template<typename A, typename B, typename = typename std::enable_if<...>::type>
inline void swap_rvalues(A&& a, B&& b);
template<typename A, typename B>
inline typename std::enable_if<...>::type swap_rvalues(A&& a, B&& b);
template <
typename A,
typename B,
typename = typename std::enable_if<
is_same_no_ref<A, B>::value &&
!std::is_const<typename std::remove_reference<A>::type>::value &&
!std::is_const<typename std::remove_reference<B>::type>::value
>::type>
inline void
swap(A&& a, B&& b) {
typename std::remove_reference<A>::type t = std::move(a);
a = std::move(b);
b = std::move(t);
}
struct B;
struct A{A(){} A(B const&){}};
struct B{B(){} B(A const&){}};
swap<A, B, void>(A(), B());
template <typename A, typename B>
inline typename std::enable_if<
is_same_no_ref<A, B>::value &&
!std::is_const<typename std::remove_reference<A>::type>::value &&
!std::is_const<typename std::remove_reference<B>::type>::value
>::type
swap_rvalues(A&& a, B&& b) {
std::swap(a, b);
}