制作一个cpp排序的元组

Sco*_*ott 7 c++

这是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)...);
    }
Run Code Online (Sandbox Code Playgroud)

我想做的是__args在创建元组之前进行排序,大概是std::sort(..., Compare comp)在用户传递适当的比较器的地方,可以用来对__args中的任何类型的东西进行排序.

但是,我对cpp相对较新,我不明白这个函数中的一半代码,并且std::sort需要一个参数结束__args,而且我不确定如何推导出它.

也请说明typename __decay_and_strip<_Elements>::__type..._Elements&&...位...

编辑因为对于任意类型组合,返回类型在编译时将是未知的,通用情况似乎是不可能的.假设所有同类型的,那么,我们替换..._ElementsT,我仍然不确定如何获得" .end()"的__args用于std::sort

cdh*_*wie 9

如果元组类型参数是同构的,可以执行此操作.(我们不能对非同类型进行排序,因为这需要重新排列类型本身,而这不是你在编译时可以做的事情.1)

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

  1. 将参数抛出到数组中.
  2. 对数组进行排序.
  3. 从数组内容中创建一个元组.

这不是太难.首先,我们需要索引技巧来索引我们的数组(对于第3步 - std::index_sequence如果你有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...> {};
Run Code Online (Sandbox Code Playgroud)

然后我们需要一种方法从参数包中剥离第一个类型来声明我们的数组(对于步骤1).作为奖励,我们将检查以确保所有类型都相同:

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...> {};
Run Code Online (Sandbox Code Playgroud)

最后,我们的分拣器实现带有帮助器来构建索引包:

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)...);
}
Run Code Online (Sandbox Code Playgroud)

看它运行.

也请说明typename __decay_and_strip<_Elements>::__type..._Elements&&...位...

我不打算解释第一个,因为包含__的标识符由C++实现保留,因此这__decay_and_strip是特定于此特定C++实现的实现细节.

_Elements&&...是一组右值参考.这允许将参数完美地转发std::tuple构造函数.


1我撒谎了.你可以在值和比较函数的情况下做到这一点constexpr,但是将它拉下来的代码将是巨大的并且不值得花时间写.