C++ 如何使用模板创建排序映射整数索引
我有以下数据结构:C++ 如何使用模板创建排序映射整数索引,c++,sorting,c++11,metaprogramming,c++14,C++,Sorting,C++11,Metaprogramming,C++14,我有以下数据结构: template <int...I> struct index {}; template <typename...T> struct data {}; template <int I, int J> struct X { static constexpr int i = I; static constexpr int j = J; }; typedef data< X<0,4>, X<1,2>
template <int...I> struct index {};
template <typename...T> struct data {};
template <int I, int J> struct X
{
static constexpr int i = I;
static constexpr int j = J;
};
typedef data< X<0,4>, X<1,2>, X<2,1>, X<1,6>, X<1,3> > data_t;
模板结构索引{};
模板结构数据{};
模板结构X
{
静态constexpr int i=i;
静态constexpr int j=j;
};
typedef数据data\u t;
其中数据不包含重复项且索引J较小,范围为0-31
我想创建一个静态索引,它包含所有X的数据位置,索引I等于某个给定值(例如I=1),按索引J排序。我发现“排序”位比较困难
例如,我想实现一个类build_索引,以便:
typedef build_index<1,data>::type_t index_t;
typedef build_index::type_t index\t;
生成与以下内容相同的内容:
typedef index<1, 4, 3> index_t;
typedef索引;
它反映了由J排序的元素X(1,J)在数据中的位置:
数据(1)处的X(1,2),数据(4)处的X(1,3),数据(3)处的X(1,6)
<>我宁愿不使用STL,因为它不适用于GCC AVR,虽然我可以选择选中的片段。< P>当你面对C++模板编程中的复杂事物时,它主要有助于将它分解成几个小步骤(就像大多数编程问题一样)。以下是一个可能的路径:
std::conditional
,当然这很容易替换。我在测试中使用的是std::is_same
,当然,您并不真正需要它(否则实现它会很简单)
std::conditional和std::的stuff+实用程序头是相同的
#include <utility>
template <int... I>
struct index
{
};
template <typename... T>
struct data
{
};
template <int I, int J>
struct X
{
static constexpr int i = I;
static constexpr int j = J;
};
typedef data<X<0, 4>, X<1, 2>, X<2, 1>, X<1, 6>, X<1, 3>> data_t;
按J排序。这是通过将元素增量插入已排序的列表来完成的。也许有更优雅的方法可以做到这一点
template <typename T, typename LessList, typename RestList>
struct insert_impl;
template <typename T, typename... Lesser>
struct insert_impl<T, data<Lesser...>, data<>>
{
using type = data<Lesser..., T>;
};
template <typename T, typename... Lesser, typename Next, typename... Rest>
struct insert_impl<T, data<Lesser...>, data<Next, Rest...>>
{
using type = typename std::conditional<
(T::j < Next::j),
data<Lesser..., T, Next, Rest...>,
typename insert_impl<T, data<Lesser..., Next>, data<Rest...>>::type>::
type;
};
template <typename T, typename SortedList>
struct insert
{
using type = typename insert_impl<T, data<>, SortedList>::type;
};
template <typename SortedList, typename UnsortedList>
struct SortImpl;
template <typename SortedList>
struct SortImpl<SortedList, data<>>
{
using type = SortedList;
};
template <typename SortedList, typename T, typename... UnsortedX>
struct SortImpl<SortedList, data<T, UnsortedX...>>
{
using type = typename SortImpl<typename insert<T, SortedList>::type,
data<UnsortedX...>>::type;
};
template <typename UnsortedList>
struct Sort
{
using type = typename SortImpl<data<>, UnsortedList>::type;
};
using sorted = typename Sort<extracted>::type;
static_assert(std::is_same<sorted, data<X<1, 2>, X<4, 3>, X<3, 6>>>::value, "");
模板
结构插入\u impl;
模板
结构插入\u impl
{
使用类型=数据;
};
模板
结构插入\u impl
{
使用type=typename std::conditional<
(T::j::
类型;
};
模板
结构插入
{
使用type=typename插入\ u impl::type;
};
模板
结构SortImpl;
模板
结构SortImpl
{
使用类型=分类列表;
};
模板
结构SortImpl
{
使用type=typename SortImpl::type;
};
模板
结构排序
{
使用type=typename SortImpl::type;
};
使用sorted=typename排序::type;
静态断言(std::is_same::value,“”);
最后,提取要查找的索引:
template <typename List>
struct Indexes;
template <typename... Data>
struct Indexes<data<Data...>>
{
using type = index<Data::i...>;
};
using result = typename Indexes<sorted>::type;
static_assert(std::is_same<result, index<1, 4, 3>>::value, "");
模板
结构索引;
模板
结构索引
{
使用类型=索引;
};
使用result=typename索引::type;
静态断言(std::is_same::value,“”);
警告:虽然我没有发现代码中有任何问题,但除了您的示例之外,我没有对其进行测试…我将分享我对这个问题的处理方法,我认为这是一种巧妙的方法。我使用了C++11
std::conditional
、C++14std::integer\u sequence
和std::make\u integer\u sequence
,所有这些都可以在线找到
让我们从您拥有的数据结构开始
template <int... Is> struct index {};
template <typename... Ts> struct list {};
template <int L, int R> struct pair {};
现在我们进入build\u index
。我们在已知的[0,32)
范围内执行桶排序。我们本可以使用通用排序算法,但作弊更有趣
template <int N, typename T> struct build_index;
// e.g., `build_index<
// 1, list<pair<0, 4>, pair<1, 2>, pair<2, 1>, pair<1, 6>, pair<1, 3>>`
template <int N, int... Ls, int... Rs>
struct build_index<N, list<pair<Ls, Rs>...>> {
// Filter for pairs where `N == lhs`, and replace the `lhs` with the index.
template <int... Is>
static auto filter(std::integer_sequence<int, Is...>)
-> concat_t<std::conditional_t<N == Ls, list<pair<Is, Rs>>, list<>>...>;
// e.g., `list<pair<1, 2>, pair<3, 6>, pair<4, 3>>`
using filtered =
decltype(filter(std::make_integer_sequence<int, sizeof...(Ls)>{}));
// `get<I>(set)` returns the `lhs` if `set` can implicitly convert to
// `pair<lhs, I>` for some `lhs`, and nothing otherwise.
template <typename... Ts> struct set : Ts... {};
template <int I, int L> static list<index<L>> get(pair<L, I>);
template <int I> static list<> get(...);
// We invoke `get<I>` for `I` in `[0, 32)` to sort `filtered`.
template <int... Is, typename... Ts>
static auto sort(std::integer_sequence<int, Is...>, list<Ts...>)
-> concat_t<decltype(get<Is>(set<Ts...>{}))...>;
// e.g., `list<index<1>, index<4>, index<3>>`
using sorted =
decltype(sort(std::make_integer_sequence<int, 32>{}, filtered{}));
// e.g., `list<1, 4, 3>`
template <int... Is> static index<Is...> indices(list<index<Is>...>);
using type = decltype(indices(sorted{}));
};
template <int N, typename... Ts>
using build_index_t = typename build_index<N, Ts...>::type;
模板结构构建索引;
//例如,“构建索引”<
//1、清单`
模板
结构构建索引{
//筛选其中'N==lhs'的对,并用索引替换'lhs'。
模板
静态自动过滤器(标准::整数\u序列)
->康考特;
//例如,`列表`
使用过滤=
decltype(filter(std::make_integer_sequence{}));
//如果`set`可以隐式转换为,则`get(set)`返回`lhs`
//对于某些'lhs','pair',没有其他的。
模板结构集:Ts..{};
模板静态列表获取(对);
模板静态列表获取(…);
//我们在`[0,32)`中为` I`调用` get`来对`过滤'进行排序。
模板
静态自动排序(std::integer\u序列,列表)
->康考特;
//例如,`列表`
使用排序=
decltype(排序(std::make_integer_sequence{},filtered{}));
//例如,`列表`
模板静态索引(列表);
使用type=decltype(索引(排序{}));
};
模板
使用build\u index\u t=typename build\u index::type;
我们得到:
using index_t = build_index_t<
1, list<pair<0, 4>, pair<1, 2>, pair<2, 1>, pair<1, 6>, pair<1, 3>>>;
static_assert(std::is_same<index<1, 4, 3>, index_t>::value, "");
使用索引\u t=build\u index\t<
1、列表>;
静态断言(std::is_same::value,“”);
允许您更改数据吗?您是否考虑过Boost元编程库(Boost.mpl)例如,你可以自己滚动排序,但是使用别人已经写的更容易。你的问题用C++ 11来标记。如果你可以使用C++ 14,它会简单很多。@ 5Go12EDER:我可以使用C++。14@fish2000在C++ 14中,您可以简单地将信息存储在<代码> CONTXPRP</CUSE>数组中,并使用普通的C++代码进行SEA。归档和排序。由于标准库还没有相关的constexpr
函数,你必须自己编写它们,这就是为什么它仍然不是一个简单的任务,这也是为什么我还没有写答案的原因。非常好!谢谢。+1祝贺你喜欢它:-)顺便说一句:当你认为你得到了你想要的答案,并且不期望得到什么的时候如果您希望尽快到达,您应该将一个答案标记为正确答案。目前,您所有的问题都列为未回答。
template <int N, typename T> struct build_index;
// e.g., `build_index<
// 1, list<pair<0, 4>, pair<1, 2>, pair<2, 1>, pair<1, 6>, pair<1, 3>>`
template <int N, int... Ls, int... Rs>
struct build_index<N, list<pair<Ls, Rs>...>> {
// Filter for pairs where `N == lhs`, and replace the `lhs` with the index.
template <int... Is>
static auto filter(std::integer_sequence<int, Is...>)
-> concat_t<std::conditional_t<N == Ls, list<pair<Is, Rs>>, list<>>...>;
// e.g., `list<pair<1, 2>, pair<3, 6>, pair<4, 3>>`
using filtered =
decltype(filter(std::make_integer_sequence<int, sizeof...(Ls)>{}));
// `get<I>(set)` returns the `lhs` if `set` can implicitly convert to
// `pair<lhs, I>` for some `lhs`, and nothing otherwise.
template <typename... Ts> struct set : Ts... {};
template <int I, int L> static list<index<L>> get(pair<L, I>);
template <int I> static list<> get(...);
// We invoke `get<I>` for `I` in `[0, 32)` to sort `filtered`.
template <int... Is, typename... Ts>
static auto sort(std::integer_sequence<int, Is...>, list<Ts...>)
-> concat_t<decltype(get<Is>(set<Ts...>{}))...>;
// e.g., `list<index<1>, index<4>, index<3>>`
using sorted =
decltype(sort(std::make_integer_sequence<int, 32>{}, filtered{}));
// e.g., `list<1, 4, 3>`
template <int... Is> static index<Is...> indices(list<index<Is>...>);
using type = decltype(indices(sorted{}));
};
template <int N, typename... Ts>
using build_index_t = typename build_index<N, Ts...>::type;
using index_t = build_index_t<
1, list<pair<0, 4>, pair<1, 2>, pair<2, 1>, pair<1, 6>, pair<1, 3>>>;
static_assert(std::is_same<index<1, 4, 3>, index_t>::value, "");