在将此标记为重复之前,我一直是here,here和here, a duplicate of the first。
我了解boost::multi_index
,并使用我缺少的环境,并且std::unordered_set
未绑定以确定的广告订单顺序存储元素。
我发现使用两个容器的概念,比如说另外一个std::vector
粗糙。
我喜欢的是一个涉及比较器的解决方案,我可以在std::set
的模板参数中使用(澄清,这可能是一个简单的函子结构,包含bool operator()()
重载,常规函数或lambda)。有可能吗?
初始化必须通过std :: container的开始迭代器/结束迭代器构造函数进行,例如在此片段中。
std::string str; cin >> str;
std::set<char>(str.begin(), str.end());
另外,另一个有趣的用例是创建一个哑哈希包装函子,允许将插入顺序推送到std::unordered_set
的模板参数。
答案 0 :(得分:3)
您不能直接将lambda表达式作为set的模板参数,因为lambda表达式是一个值,而set的模板参数是一个类型。问题的明显更正,无论使用lambda和decltype
的构造是否可行,都会导致一个有趣的问题,即lambda表达式表示唯一类型(“闭包类型”),所以你永远不能创建两个相同闭包类型的单独lambda表达式。*
然而,在更抽象的意义上,您可以使用模板参数推导在本地上下文中实现您想要的内容,例如:
template <typename F>
int f(int* first, int* last, F comp)
{
std::set<int, F> s(comp);
while (first != last) s.insert(*first++);
...
}
现在,您可以使用lambda表达式作为参数调用f
,从而有效地“使用lambda作为集合的比较器”。或者,对于一个更简单的示例,您可以为lambda创建一个命名变量(将所有模板推导放入单个auto
中:
auto comp = [](...) { ... };
std::set<int, decltype(comp)> s(comp);
*)有一项建议允许lambda在未评估的上下文中解决这一问题,但其前景尚不确定。它有一些有趣的副作用,比如使闭包类型影响名称修改。
答案 1 :(得分:1)
保留插入顺序的adt是std :: vector。 您可以像这样轻松地将其包装起来以获得类似std :: set的行为:
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;
template < typename T >
class VectorSet : public vector<T> {
public:
using iterator = typename vector<T>::iterator;
using value_type = typename vector<T>::value_type;
pair<iterator, bool> insert (const value_type& val) {
auto it = ::find(this->begin(), this->end(), val);
if (it == this->end())
it = ::vector<T>::insert(this->end(), val);
return pair<iterator, bool>(it, true);
}
};
int main()
{
VectorSet<int> my;
my.insert(1);
my.insert(4);
my.insert(3);
my.insert(4);
for (auto & v : my) {
cout << v << endl;
}
return 0;
}
答案 2 :(得分:0)
除非您使用其他索引,否则不能。两种方法:
<强> Live On Coliru 强>
#include <set>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
#include <iostream>
string read_word() {
string str;
cin >> str;
return str;
}
int main() {
using Ref = std::reference_wrapper<char const>;
auto const str = read_word();
std::cout << "Word: " << str << "\n";
auto v = [&]() -> vector<Ref> {
set<Ref> u(str.begin(), str.end());
return {u.begin(), u.end()};
}();
std::cout << "Unique: " << string(v.begin(), v.end()) << "\n";
auto pos = [str](char ch) { return str.find(ch); };
std::sort(v.begin(), v.end(), [pos](auto& a, auto& b) { return pos(a) < pos(b); });
std::cout << "Insertion: " << string(v.begin(), v.end()) << "\n";
}
打印例如。
Word: pineapple
Unique: aeilnp
Insertion: pineal
相同的交易
<强> Live On Coliru 强>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
namespace bmi = boost::multi_index;
using Index = bmi::multi_index_container<char,
bmi::indexed_by<
bmi::sequenced<>,
bmi::ordered_unique<bmi::tag<struct unique>, bmi::identity<char> >
> > ;
#include <iostream>
std::string read_word() {
std::string str;
std::cin >> str;
return str;
}
int main() {
auto const str = read_word();
std::cout << "Word: " << str << "\n";
Index idx(str.begin(), str.end());
std::cout << "Insertion: " << std::string(idx.begin(), idx.end()) << "\n";
auto& u = idx.get<unique>();
std::cout << "Unique: " << std::string(u.begin(), u.end()) << "\n";
}
打印
Word: pineapple
Insertion: pineal
Unique: aeilnp
答案 3 :(得分:0)
我认为一个怪异的解决方案(尽管没有涉及任何集合的解决方案)可能是使用元素类型的std::map
和std::time_point
作为键类型。这将确保插入顺序(如果根本没有)。