我有一个应用程序,首先生成一个std::vector<int>
对象。然后,需要对这个被视为std::set<int>
的对象执行一些操作,其中顺序无关紧要,重复不算数。
目前,我从std::vector<int>
对象显式地构造了一个类型为std::set<int>
的对象。示例如下:
#include <cstdio>
#include <set>
#include <vector>
void printset(std::set<int>& Set) {
printf("Printing Set Elements: ");
for (std::set<int>::iterator siter = Set.begin(); siter != Set.end(); ++siter) {
int val = *siter;
printf("%d ", val);
}
printf("n");
}
void printvec(std::vector<int>& Vec) {
printf("Printing Vec Elements: ");
for (size_t i = 0, szi = Vec.size(); i < szi; ++i) {
int val = Vec[i];
printf("%d ", val);
}
printf("n");
}
int main()
{
std::vector<int> VecInt{ 6, 6, 5, 5, 4, 4 };
std::set<int> SetInt(VecInt.begin(), VecInt.end());
printvec(VecInt);
printset(SetInt);
}
我正在试着看看我是否可以使用Boost.MultiIndex
来达到这个目的。Boost.MultiIndex
状态简介:
Boost.MultiIndex。您可以使用Boost.MultiIndex定义一个容器,该容器提供向量接口和集合接口,而不必将元素存储在向量和集合中,然后连续同步容器。
这正是我正在做的(使用多个容器,然后不断地从另一个容器创建一个(,而我想创建一次(多索引(容器,然后提供一个向量接口和一个集合接口。
通过查看各种示例,例如这里和这里,不清楚如何将这些示例修改为上面的代码示例。
理想情况下,我想在上面的代码示例中做以下操作:
MultiIndexContainer vec_set_container;
vec_set_container.push_back(6);//or anything equivalent for the MultiIndexContainer
vec_set_container.push_back(6);
vec_set_container.push_back(5);
vec_set_container.push_back(5);
vec_set_container.push_back(4);
vec_set_container.push_back(4);
printvec(vec_set_container.Some_Function_That_Exposes_Vector_Interface());
printset(vec_set_container.Some_Function_That_Exposes_Set_Interface());
如何使用Boost.MultiIndex
实现这一点?
随机访问索引将与;矢量";界面
有序的唯一索引将与";设置";界面
但是,如果您有一个唯一的索引,这将防止插入重复项。所以,你会得到:
实时编译器资源管理器
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index_container.hpp>
#include <fmt/ranges.h>
namespace bmi = boost::multi_index;
using Table = bmi::multi_index_container< //
int,
bmi::indexed_by<
bmi::random_access<bmi::tag<struct asVector>>,
bmi::ordered_unique<bmi::tag<struct asSet>, bmi::identity<int>>>>;
int main()
{
Table data{ 6, 6, 5, 5, 4, 4 };
fmt::print("As vec {}nAs set {}n", //
data.get<asVector>(), //
data.get<asSet>());
}
打印
As vec {6, 5, 4}
As set {4, 5, 6}
现在,我认为;最好的";这样做可以使顺序索引不唯一(因此,模拟std::multiset
而不是std::set
(:实时编译器资源管理器
bmi::ordered_non_unique<bmi::tag<struct asSet>, bmi::identity<int>>
打印
As vec [6, 6, 5, 5, 4, 4]
As set {4, 4, 5, 5, 6, 6}
如果你想遍历独特的元素,使用测距适配器的成本最低:
使用Boost实时
fmt::print("As vec {}nAs set {}n", // data.get<asVector>(), // data.get<asSet>() | boost::adaptors::uniqued);
使用RangeV3实时
fmt::print("As vec {}nAs set {}n", // data.get<asVector>(), // data.get<asSet>() | ranges::views::unique);
使用标准范围;我不能让这个工作,但它真的应该像
std::ranges::unique(data.get<asSet>())
一样
所有打印
As vec {6, 6, 5, 5, 4, 4}
As set {4, 5, 6}
其他想法
如果您不需要随机访问,那么sequenced
索引可能更适合您。注意,这个接口附带了方便的unique()
和sort()
方法(就像std::list
一样(。
评论更新
以下是对评论的综合回应:
实时编译器资源管理器
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index_container.hpp>
#include <fmt/ranges.h>
#include <random>
namespace bmi = boost::multi_index;
template <typename T>
using ListSet = bmi::multi_index_container< //
T,
bmi::indexed_by<
bmi::sequenced<bmi::tag<struct byInsertion>>, //
bmi::ordered_unique<bmi::tag<struct Ordered>, bmi::identity<T>> //
>>;
int main()
{
ListSet<int> data;
std::mt19937 prng{99}; // "random" seed
for (std::uniform_int_distribution d(1, 10); data.size() < 5;) {
int el = d(prng);
if (auto [it, unique] = data.push_back(el); not unique) {
fmt::print("Element {} duplicates index #{}n", el,
std::distance(begin(data), it));
}
}
fmt::print("By insertion {}nOrdered {}n", data, data.get<Ordered>());
}
打印
Element 9 duplicates index #3
Element 8 duplicates index #1
By insertion [7, 8, 5, 9, 1]
Ordered {1, 5, 7, 8, 9}