c stl使用红色树木将数据存储在std::set
和std::map
中。我注意到set::iterator
实际上是红色黑树的常量迭代器的打字机:
//All code snippets taken from SGI STL. https://www.sgi.com/tech/stl/
typedef _Rb_tree<key_type, value_type, _Identity<value_type>, key_compare, _Alloc> _Rep_type;
typedef typename _Rep_type::const_iterator iterator;
这是合理的,因为用户不应该通过迭代器修改集合的内容。但是set
必须实现诸如insert
和erase
之类的操作,该操作要求Red-Black树的非const迭代器。SGI STL使用C风格的演员来执行此操作:
void erase(iterator __position) {
typedef typename _Rep_type::iterator _Rep_iterator;
_M_t.erase((_Rep_iterator&)__position);
}
我想知道:
- 为什么这个铸件安全?它将
_Rep_type::const_iterator
铸造为_Rep_type::iterator&
。 - 如何用C 样式写演员?我已经尝试这样做:
static_cast
和const_cast
都不会完成这项工作。reinterpret_cast
可以编译,但我不确定它是否与C风格的铸件相同。
iterator
和 _Rep_type::iterator
是同一类模板的实例,前者使用const
合格类型,而后者则使用相同但非const
类型。这样的东西:
template <class T, class U>
struct B {};
using S = B<int&, int*>;
using Sconst = B<const int&, const int*>;
因此,对于您的问题:
- 这是安全的,因为两种类型具有完全相同的内存布局。
- 您不能使用
static_cast
,因为编译器认为要无关的类型。您必须带来重型大炮,reinterpret_cast
:
int test() {
S s;
Sconst& sconst = reinterpret_cast<Sconst&>(s);
}
a c-cast没有直接映射到一个特定的C 铸造。
,但是可以将C级映射到一个或多个C 铸件。
进行C播时,您可以想到编译器按顺序尝试这组C 铸件。第一个有效的是C 编译器将执行的操作:(另请参见N4917 7.6.3显式类型转换(cast note法)[Expr.cast])
- const_cast
- static_cast
- static_cast后跟const_cast
- reinterpret_cast
- reinterpret_castFollow const_cast
因此,查看您的示例,它看起来像是选项3或5(但需要使用编译器尝试一下以确保)。
(_Rep_iterator&)__position
// Maps to:
const_cast<_Rep_iterator&>(static_cast<_Rep_iterator const&>(__position))
// or
const_cast<_Rep_iterator&>(reinterpret_cast<_Rep_iterator const&>(__position))