使用C++ 14,我们可以将一些关联容器(如std :: set)的元素与存储在容器中的其他类型进行比较.当比较器is_transparent表示为一种类型时,它应该起作用(参见例如std :: set :: find).
假设我有一个字符串包装器,它对字符串执行一些检查(如果它的格式是有效格式等等 - 不是很重要,但构造它足够重,我想避免它+它可以抛出异常)并且它是存储在std :: set中以具有唯一值的容器.我该如何为它写一个比较器?它应该像下面那样吗?我能超载并使用我sw::operator<()来实现同样的目标吗?
class sw
{
public:
explicit sw(const std::string& s) : s_(s) { /* dragons be here */ }
const std::string& getString() const { return s_; }
bool operator<(const sw& other) const { return s_ < other.s_; }
private:
std::string s_;
};
struct Comparator
{
using is_transparent = std::true_type;
bool operator()(const sw& lhs, const std::string& rhs) const { return lhs.getString() < rhs; } …Run Code Online (Sandbox Code Playgroud) 我需要通过保存set.find()返回的迭代器来跟踪std :: set元素.
我的问题是插入和删除其他元素是否使获得的迭代器无效?从我做过的简单测试我可以看出它不是,但我想确保这个功能是设计的.
s1和s2是集合(Python集或C++ std :: set)
要将s2的元素添加到s1(set union),你可以做
Python: s1.update(s2)
C++: s1.insert(s2.begin(), s2.end());
Run Code Online (Sandbox Code Playgroud)
要从s1中删除s2的元素(设置差异),你可以这样做
Python: s1.difference_update(s2)
Run Code Online (Sandbox Code Playgroud)
这与C++相当的是什么?代码
s1.erase(s2.begin(), s2.end());
Run Code Online (Sandbox Code Playgroud)
不起作用,因为s1.erase()需要来自s1的迭代器.代码
std::set<T> s3;
std::set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(s3, s3.end());
s1.swap(s3);
Run Code Online (Sandbox Code Playgroud)
可行,但似乎过于复杂,至少与Python相比.
有更简单的方法吗?
我有一堆完整的重复数据,我想消除重复.你知道,例如[1,1,3,5,5,5,7]变成[1,3,5,7].
看起来我可以使用std :: map或std :: set来处理这个问题.但是我不确定(a)是否只是将所有值插入容器中,或者(b)检查它们是否已经存在于容器中并且仅在它们不存在时插入 - 是否插入非常有效?即使有更好的方法......你能建议一个快速的方法吗?
另一个问题 - 如果我存储在其中的数据不像整数那么简单,而是一个自定义类,std :: map如何管理以正确存储(哈希?)数据以便通过运算符快速访问[ ]?
以下代码:
#include <iostream>
#include <set>
#include <algorithm>
std::set<int> s;
int main()
{
s.insert(1);
s.insert(2);
std::remove(s.begin(), s.end(), 1);
}
Run Code Online (Sandbox Code Playgroud)
不用gcc 4.7.2编译:
$ LANG=C g++ test.cpp
In file included from /usr/include/c++/4.7/algorithm:63:0,
from test.cpp:3:
/usr/include/c++/4.7/bits/stl_algo.h: In instantiation of '_FIter std::remove(_FIter, _FIter, const _Tp&) [with _FIter = std::_Rb_tree_const_iterator<int>; _Tp = int]':
test.cpp:12:38: required from here
/usr/include/c++/4.7/bits/stl_algo.h:1135:13: error: assignment of read-only location '__result.std::_Rb_tree_const_iterator<_Tp>::operator*<int>()'
Run Code Online (Sandbox Code Playgroud)
所以我去了定义,fset::iterator我在gcc的实现中发现了这个(文件../c++/4.7/bits/stl_set.h,来自125):
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 103. set::iterator is required to be modifiable,
// but this allows modification of …Run Code Online (Sandbox Code Playgroud) 我已经读过这篇SO帖子了,这个也是关于std::set迭代过程中元素的擦除.但是,似乎C++ 17中存在一个更简单的解决方案:
#include <set>
#include <iostream>
int main(int argc,char **argv)
{
std::set<int> s;
s.insert(4);
s.insert(300);
s.insert(25);
s.insert(-8);
for (auto it:s)
{
if (it == -8)
{
s.erase(it);
}
}
std::cout << "s = {";
for (auto it:s)
{
std::cout << it << " ";
}
std::cout << "}\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我编译并运行它时,一切都很完美:
$ g++ -o main main.cpp
$ ./main
s = {4 25 300 }
Run Code Online (Sandbox Code Playgroud)
擦除这样的元素有什么警告吗?谢谢.
为什么我不能有一个std::set或std::unordered_set的std::functionS'
有什么方法可以让它工作吗?
这里的"const"是编译问题的原因.但是,自己实现了STL树,我无法理解为什么.
这是代码:
#include <iostream>
#include <set>
int main ()
{
int a;
// I want the set to carry the "promise"
// to keep the pointers constant
std :: set < int * const > x;
x . insert ( &a );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是错误:
In file included from /usr/include/c++/7/string:48:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from demo.cpp:1:
/usr/include/c++/7/bits/stl_function.h: In instantiation of ‘struct std::_Identity<int* const>’:
/usr/include/c++/7/bits/stl_tree.h:2091:29: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) …Run Code Online (Sandbox Code Playgroud) 我们以下面的代码为例。
auto cmp = [](ll a, ll b) {
return gcd(12, a) < gcd(12, b);
};
set<ll, decltype(cmp)> s(cmp);
for(ll i = 0; i < 2; i++){
ll x;
cin >> x;
s.insert(x);
cout << "Success! \n";
}
Run Code Online (Sandbox Code Playgroud)
我定义了新的比较器,通过它们的最大公约数与 12 进行比较。
首先我成功插入5。然后我尝试插入7,但没有成功。
我知道 gcd(12, 5) = gcd(12, 7) = 1。
但我不明白如何std::set检查 5 是否等于 7。
用我给的comparator comp可以查出gcd(12, 7)不小于gcd(12, 5) ,但是怎么算出gcd(12, 7)等于gcd(12, 5) ?