神必 cpp 语法合集
你也许不会写的
反向遍历 std::map
的时候删除迭代器
2023.4.19
decltype(mp)::iterator p = ++mp.erase(++it.base());
it = std::make_reverse_iterator(p);
demo: c++17
#include <map>
#include <iostream>
int main() {
std::map<int, int> mp{{1, 2}, {3, 1}, {2, 1}};
for (auto it = mp.rbegin(); it != mp.rend(); ) {
if (it->first == 2) {
decltype(mp)::iterator p = ++mp.erase(++it.base());
it = std::make_reverse_iterator(p);
} else {
it ++;
}
}
for (auto &[k, v] : mp) {
std::cout << k << ' ' << v << '\n';
}
return 0;
}
原理
std::map::erase
要求传入 {, const_}iterator
因此这个情景下的 {, const_}reverse_iterator
不奏效。所以考虑转换成 iterator
之后再 erase,之后再转回 reverse_iterator
。根据两种迭代器的对应规则,有:
也就是说,直接对反向迭代器 it
调用 std::make_reverse_iterator
得到的并不是期待的,而 std::next(it)
才对应正确的值。
另外要从反向迭代器得到正向迭代器,除了 std::make_reverse_iterator
再翻转一次也可以直接使用 std::reverse_iterator
对应的成员函数 base()
得到。
你也许会写错的
assert 多逗号
2023.4.20
最小 demo
#include <cassert>
struct point {
int x, y;
bool operator==(const point &_) const = default;
};
int main() {
assert(point{1, 2} == point{1, 2});
return 0;
}
报错:[Error] macro "assert" passed 3 arguments, but takes just 1
应该打个括号,patch:
- assert(point{1, 2} == point{1, 2});
+ assert((point{1, 2} == point{1, 2}));
原理
Stackoverflow it: https://stackoverflow.com/questions/69783399/error-macro-assert-passed-2-arguments-but-takes-just-1
翻译
预处理器对 C++ 语法的认知十分初级,在你的代码中有两个逗号,因此宏认为你传递了三个参数。
群友说
疑惑
真相
锐评
忠告
证明确实是三个参数的 demo
#include <cassert>
#define get_argc_(_1, _2, _3, _4, _5, _6, _7, N, ...) N
#define get_argc(...) get_argc_(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
int main() {
assert(3 == get_argc(std::pair{1, 1} != std::pair{1, 1}));
return 0;
}