C++ 可变参数函数就地对参数进行排序

C++ Variadic Function To Sort Arguments In-place

在实现二进制搜索问题的变体时,我需要重新排序切片点(即开始、中间、结束),以便将它们存储在相应的变量中(例如 (1,5,2) -> (1,2,5))。这对于一些 if statementsswaps 来说相当简单。然而,作为一个思想实验,我现在有兴趣将其推广到 n 许多 T 类型变量。我开始尝试一些直观的解决方案,作为起点,我想到了这个模板函数:

template<typename T>
void 
sortInPlace(
    std::function<bool (const T&, const T&)> compareFunc,
    T& start, 
    T& mid, 
    T& end)
    {
        std::vector<T> packed {start, mid, end};
        std::sort(packed.begin(), packed.end(), compareFunc);
        auto packedAsTuple = make_tuple(packed[0], packed[1], packed[2]);
        std::tie(start, mid, end) = packedAsTuple;
    }

当我 运行 以下时,使用 typedef std::pair<int,int> Pivot:

//Comparison function to sort by pair.first, ascending:
std::function<bool(const Pivot&, const Pivot&)>
  comp =[](const Pivot & a, const Pivot & b) {
     return std::get < 0 > (a) < std::get < 0 > (b);
  };

int main(){
    Pivot a(8,1);
    Pivot b(2,3);
    Pivot c(4,6);

    sortInPlace(comp,a,b,c);
}

事实证明这是按预期工作的:

a after sort: 2, 3
b after sort: 4, 6
c after sort: 8, 1

理想情况下,接下来的步骤是将此模板转换为可变参数模板,但我在实现这一点时遇到了麻烦。关于当前版本,我还有一些困扰我的事情:

  1. std::vector 的使用是一个武断的决定。我这样做是因为我不清楚什么 structure/container 最适合用于打包这些值。在我看来,结构的选择需要构造、排序和 unpacked/converted 到元组很容易,我不确定是否有这样一个神奇的结构。
  2. 为了让事情顺利进行,我不得不手动解决 packing/unpacking 参数。我也不清楚如何使用 std::tie 或任何其他 unpacking/moving 具有可变数量(即编译时未知)元素的操作。
  3. 虽然没有特别的理由专门使用 stl functions/structures,但我很惊讶地发现没有直观的方法可以使用 stl 中提供的抽象来实现这一点。因此,我更感兴趣的是在 stl 之外使用最少的帮助来实现我的目标。

我开始了这个思想实验,希望最终得到一个句法正确的 std::move(std::sort({x,y,z}, comp), {x,y,z}) 版本,考虑到我的研究到目前为止把我带到了什么地方,我开始认为我过于复杂了这个问题。非常感谢任何帮助、见解或建议!

一种可能的 C++17 解决方案 std::sort 概括了您的示例:

template<class Comp, class... Ts>
void my_sort(Comp comp, Ts&... values) {
    using T = std::common_type_t<Ts...>;
    T vals[]{std::move(values)...};

    std::sort(std::begin(vals), std::end(vals), comp);

    auto it = std::begin(vals);
    ((values = std::move(*it++)), ...);
}

using Pivot = std::pair<int, int>;

const auto comp = [](Pivot a, Pivot b) {
    return std::get<0>(a) < std::get<0>(b);
};

Pivot a(8, 1);
Pivot b(2, 3);
Pivot c(4, 6);

my_sort(comp, a, b, c);

如果包中的参数数量N 很少,则根本不需要std::sort。只需一系列(硬编码)比较(对于小 N,最小比较次数是确切已知的)就可以完成这项工作 - 请参阅 sec。 5.3 Knuth 的 TAOCP 卷的最佳排序。 3.