做一个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),其中用户可以在适当的比较器中传递,该比较器可以用于分类任何类型的事物最终在__args中。

但是,我对CPP相对较新,我不了解此功能中的一半代码,并且std::sort需要__args结束的参数,我不确定如何得出。<<<<<<<<<</p>

也请解释typename __decay_and_strip<_Elements>::__type..._Elements&&...位...

edit 由于对于任意类型组合,返回类型在编译时将是未知的,因此似乎是不可能的。然后,假设所有类型的类型都相同,然后我们将..._Elements替换为T,我仍然不确定如何在std::sort

中获取__args的" .end()"

如果元组类型参数是均匀的,则可以完成。(我们不能对非均匀类型进行排序,因为这需要重新排列类型本身,这不是您可以在编译时做的事情。 1

假设均匀类型,解决方案基本上归结为:

  1. 将论点扔进数组。
  2. 对数组进行排序。
  3. 从数组内容中制作元组。

这并不难。首先,我们需要索引技巧来索引我们的数组(对于第3步 - 如果您有C 14,则可以使用std::index_sequence):

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)。作为奖励,我们将进行检查以确保所有类型都是相同的:

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...> {};

最后,我们使用助手实施分类器来构建指数包:

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)...);
}

看到它运行。

也请解释typename __decay_and_strip<_Elements>::__type..._Elements&&...位...

我不会解释第一个,因为包含__的标识符是由C 实现保留的,因此该__decay_and_strip是该特定C 实现的实现详细信息。

_Elements&&...是一包RVALUE参考。这允许参数完美地转发到std::tuple构造函数。


1 我撒谎。如果值和比较函数为constexpr,则可以执行此操作,但是要删除它的代码将是巨大的,不值得写的时间。

最新更新