制作一个cpp排序元组 [英] Making a cpp sorted tuple

查看:109
本文介绍了制作一个cpp排序元组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是标准库中 std :: make_tuple 的代码。

template<typename... _Elements>
    inline tuple<typename __decay_and_strip<_Elements>::__type...>
    make_tuple(_Elements&&... __args)
    {
    typedef tuple<typename __decay_and_strip<_Elements>::__type...>
    __result_type;
    return __result_type(std::forward<_Elements>(__args)...);
    }

我想做的是对进行排序__args 创建元组之前,大概使用 std :: sort(...,Compare comp),在此用户可以通过适当的比较器

What I would like to do, is to sort __args before creating the tuple, presumably with std::sort(..., Compare comp) where the user passes in an appropriate comparator that can be used to sort whatever type things end up in __args.

但是,我对cpp还是比较陌生,我不了解此函数中的一半代码,而 std :: sort 需要一个参数作为 __ args 的结尾,我不确定如何得出

However, I'm relatively new to cpp, I don't understand half of the code in this function, and the std::sort needs an argument for the end of __args, and I'm not sure how to derive that.

还请说明 typename __decay_and_strip< _Elements> :: __ type ... _Elements& ... 位...

编辑因为对于任意类型的组合,返回类型在编译时将是未知的,通用情况似乎是不可能的。假设所有相同的类型,然后我们用 T 替换 ..._ Elements ,我仍然不确定获取 __ args .end(),以用于 std :: sort

EDIT Since for arbitrary type combinations the return type would then be unknown at compile time, the generic case seems to be not possible. Supposing all the same type, then, and we replace ..._Elements with T, I'm still unsure how to get the ".end()" of __args for use in std::sort

推荐答案

如果元组类型参数是同质的,则可以完成 。 (我们无法对非均匀类型进行排序,因为这将需要对类型本身进行重新排列,而这不是您在编译时可以执行的操作。 1

This can be done if the tuple type arguments are homogeneous. (We can't sort non-homogeneous types because that would require rearrangement of the types themselves, and that's not something you can do at compile time.1)

假设同构类型,解决方案基本上可以归结为:

Assuming homogeneous types, the solution basically boils down to this:


  1. 将参数放入数组。

  2. 对数组进行排序。

  3. 从数组内容中创建一个元组。

这不太难。首先,我们需要 indices技巧为数组建立索引(对于第3步-您可以使用 std :: index_sequence ,如果您使用的是C ++ 14):

This isn't too hard. First we need the indices trick to index our array (for step 3 -- you can use std::index_sequence instead if you have C++14):

template <std::size_t... Is>
struct indices {};

template <std::size_t N, std::size_t... Is>
struct build_indices
  : build_indices<N-1, N-1, Is...> {};

template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};

然后,我们需要一种方法来从参数包中剥离第一个类型以声明我们的数组(对于第1步)。另外,我们会检查所有类型是否相同:

Then we need a way to peel off the first type from the parameter pack to declare our array (for step 1). As a bonus, we'll have it check to make sure all the types are the same:

template <typename...>
struct pack_type;

template <typename Head>
struct pack_type<Head>
{
    using type = Head;
};

// Will fail deduction on a non-homogeneous pack.
template <typename Head, typename... Tail>
struct pack_type<Head, Head, Tail...> : pack_type<Head, Tail...> {};

最后,我们的排序器实现带有一个帮助程序来建立索引包:

Finally, our sorter implementation with a helper to build the indices pack:

template <std::size_t... I, typename Comparer, typename... Ts>
std::tuple<Ts...> make_sorted_tuple_impl(indices<I...>, Comparer const &c, Ts && ...args)
{
    typename pack_type<Ts...>::type values[sizeof...(Ts)] = { std::forward<Ts>(args)... };

    std::sort(std::begin(values), std::end(values), c);

    return std::make_tuple(std::forward<Ts>(values[I])...);
}

// Special case to handle empty tuples.
template <typename Comparer>
std::tuple<> make_sorted_tuple_impl(indices<>, Comparer const &)
{
    return std::tuple<>();
}

template <typename Comparer, typename... Ts>
std::tuple<Ts...> make_sorted_tuple(Comparer const &c, Ts && ...args)
{
    return make_sorted_tuple_impl(build_indices<sizeof...(Ts)>(), c, std::forward<Ts>(args)...);
}

查看其运行情况。

See it run.


也请解释一下 typename __decay_and_strip< _Elements> :: __ type ... _Elements& ...... 位...

我不会解释第一个,因为包含 __ 的标识符是由C ++实现保留的,因此此 __ decay_and_strip 是特定于此特定C ++实现的实现细节。

I'm not going to explain the first because identifiers containing __ are reserved by the C++ implementation, so this __decay_and_strip is an implementation detail specific to this particular C++ implementation.

_Elements& ;& ... 是一包右值引用。这样可以将参数完美转发 std :: tuple 构造函数。

_Elements&&... is a pack of rvalue references. This allows the arguments to be perfectly forwarded to the std::tuple constructor.

1 我撒了谎。如果值和比较函数为 constexpr ,则可以执行此操作,但是将其提取的代码将非常庞大,不值得花时间编写。

1 I lied. You can do it if the values and the compare function are constexpr, but the code to pull it off will be huge and not worth the time to write.

这篇关于制作一个cpp排序元组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆