这是标准库中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 )
假设均匀类型,解决方案基本上归结为:
- 将论点扔进数组。
- 对数组进行排序。
- 从数组内容中制作元组。
这并不难。首先,我们需要索引技巧来索引我们的数组(对于第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
,则可以执行此操作,但是要删除它的代码将是巨大的,不值得写的时间。