为什么 std::swap 不交换 std::reference_wrapper 的底层对象?

art*_*sse 4 c++

背景:

我正在尝试实现一个函数,我们称之为它mysort,它接受可变数量的相同类型的参数并对它们进行排序。例如下面的代码应该打印1 2 3

template <typename ... Args>
void mysort(Args& ... args);
int main(int, char**)
{
    int x = 3;
    int y = 1;
    int z = 2;
    mysort(x, y, z);
    cout << x << ' ' << y << ' ' << z << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我尝试过的:

这是我想出的解决方案

#include <array>
#include <algorithm>
#include <functional>

template <typename T, typename ... Args>
void mysort(T& t, Args& ... args)
{
    constexpr size_t n = sizeof...(Args) + 1;
    std::array<std::reference_wrapper<T>, n> temp = { std::ref(t), std::ref(args)... };
    std::sort(temp.begin(), temp.end());
}
Run Code Online (Sandbox Code Playgroud)

但这个解决方案不起作用,因为std::swapwith 的作用std::reference_wrapper不是我所期望的(我希望任何更改都应该更改为其创建的std::reference_wrapper对象)。std::reference_wrapper

添加后一切开始工作

namespace std
{
    void swap(std::reference_wrapper<int>& a, std::reference_wrapper<int>& b) noexcept
    {
        std::swap(a.get(), b.get());
    }
}
Run Code Online (Sandbox Code Playgroud)

我不确定标准是否需要std::sort使用std::swap,所以我认为这不是一个完整的解决方案并且依赖于实现。

总结:

我对 std::reference_wrapper 的想法是它的行为应该像引用一样,但情况似乎并非如此。这是我的问题:

  1. 最好的实施方式是什么mysort
  2. 为什么该标准没有提供交换底层对象std::swap的规范?std::reference_wrapper

预先感谢您的回答!

jwe*_*rek 5

要点std::reference_wrapper是它是可复制和可分配的,“可分配”是指引用包装器可以像普通引用那样重新绑定到新值。

你所做的与它的目的相反。在您的情况下,当实现std::sort临时数组中的交换项时,它会重新绑定引用,但这不是您想要的。您希望它交换实际项目而不是参考。

一种方法是对std::sort参数的副本进行排序,然后按排序顺序将它们分配回引用参数:

template <typename T, typename ... Args>
void mysort(T& t, Args& ... args)
{
    constexpr size_t n = sizeof...(Args) + 1;
    std::array<T, n> temp = { t, args... };
    std::sort(temp.begin(), temp.end());
    std::tie(t, args...) = std::tuple_cat(temp);
}
Run Code Online (Sandbox Code Playgroud)

在这里,我将它们包装在一个元组中,以便我可以通过 进行分配std::tie。可能有某种方法可以用更少的副本来做到这一点,但这就是我想到的。