繁体   English   中英

如何对两个容器元组进行排序?

[英]How do I sort two tuples of containers?

我有两个元组,每个元组包含不同类型的容器。

std::tuple<containerA<typesA>...> tupleA;
std::tuple<containerB<typesB>...> tupleB;

因此,作为示例, tupleA可能会像这样定义:

std::tuple<list<int>, list<float>> tupleA;

containerAcontainerB这两个容器是不同的类型。 typesAtypesB不相交。 我想按大小对元组内的容器进行排序,并能够按类型访问它们。 所以,举个例子

std::tuple<list<int>, list<float>> tupleA {{2}, {3.3f, 4.2f}};
std::tuple<deque<double>, deque<uint8_t>> tupleB {{2.0, 1.2, 4.4}, {}};

auto sortedArray = sort(tupleA, tupleB);
sortedArray == {deque<uint8_t>, list<int>, list<float>, deque<double>};
sortedArray.get<list<float>>() == {3.3f, 4.2f};
std::get<list<int>>(tupleA).push_back(4);
std::get<list<int>>(tupleA).push_back(5);
std::get<list<int>>(tupleA).push_back(6);
sortedArray = sort(tupleA, tupleB);
sortedArray == {deque<uint8_t>, list<float>, deque<double>, list<int>};

最重要的部分是我必须存储sortedArray并且元组中元素的大小可能会改变。 我无法创建这样的sort功能。 访问sortedArray的实际语法并不重要。

我尝试使用naive索引到sortedArray的容器数据,例如使用std::pair<A, 1>来引用元组A中的第二个元素,但是我无法通过它访问元组的信息,因为它不是一个constexpr

这是可能的但不容易。

首先,您需要生成N个元素的每个排列的编译时列表(它们有N个阶乘)。

写入运行时和编译时置换对象(单独)。

制作从排列到索引的运行时映射。 (地图步骤)

将您的元组转换为(索引,大小)的向量。 按大小排序。 提取排列。 将其映射到排列集的索引。 (排序步骤,使用地图步骤)

编写一个“魔术开关”,它接受一个函数对象f和一个置换索引,并用编译时置换来调用f (神奇的一步)

编写采用编译时排列的代码,并根据它重新排序元组。 (重新订购步骤)

编写带有函数对象ftuple 做(排序步骤)。 做(魔术步骤),向它提供第二个函数对象g ,它接受传入的排列和元组和(重新排序步骤),然后用它调用f

调用,它这个功能bob

std::tuple<list<int>, list<float>> tupleA {{2}, {3.3f, 4.2f}};
std::tuple<deque<double>, deque<uint8_t>> tupleB {{2.0, 1.2, 4.4}, {}};

bob(concat_tuple_tie(tupleA, tupleB), [&](auto&& sorted_array){
  assert( std::is_same<
    std::tuple<deque<uint8_t>&, list<int>&, list<float>&, deque<double>&>,
    std::decay_t<decltype(sorted_array)>
  >::value, "wrong order" );
  sortedArray.get<list<float>>() == {3.3f, 4.2f};
});
std::get<list<int>>(tupleA).push_back(4);
std::get<list<int>>(tupleA).push_back(5);
std::get<list<int>>(tupleA).push_back(6);
bob(concat_tuple_tie(tupleA, tupleB), [&](auto&& sorted_array){
  assert( std::is_same<
    std::tuple<deque<uint8_t>&, list<float>&, deque<double>&, list<int>&>,
    std::decay_t<decltype(sorted_array)>
  >::value, "wrong order" );
});

就个人而言,我怀疑你需要这样做。

我可以做到这一点,但可能需要几个小时,所以我不打算这样做。 您可以查看我的魔术开关代码以获得上述最神奇的功能。 另一个难点是排列步骤。

请注意,代码使用延续传递样式。 另请注意,lambda的每个排列都会被实例化,包括错误的排列,因此您的代码必须对每个排列都有效。 这可能会导致疯狂的代码膨胀。

另一种解决方案可能涉及在容器周围创建类型擦除包装器并简单地对它们进行排序,但这不是您要求的。

描述的问题听起来非常像你想要动态多态,而不是静态多态 - 而你解决它的困难是因为你一直试图用静态多态的工具来表达。

即你需要,让你选择收集的数据的类型和运行时类型的集合(或指针集合)类型(层次),但仍然提供了一个统一的接口,你需要这样的功能size (例如,通过继承和虚函数)。

例如,草图的开头可能看起来像

struct SequencePointer
{
    virtual size_t size() const = 0;
    virtual boost::any operator[](size_t n) const = 0;
};

template <typename Sequence>
struct SLSequencePointer
{
    const Sequence *ptr;
    size_t size() const { return ptr->size(); }
    boost::any operator[](size_t n) const { return (*ptr)[n]; }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM