背景:
我正在尝试实现一个函数,我们称之为它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::swap
with 的作用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 的想法是它的行为应该像引用一样,但情况似乎并非如此。这是我的问题:
mysort
?std::swap
的规范?std::reference_wrapper
预先感谢您的回答!
要点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
。可能有某种方法可以用更少的副本来做到这一点,但这就是我想到的。