Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用右值交换_C++_Swap_Move Semantics_Rvalue Reference - Fatal编程技术网

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);
}