迭代器const_iterator的演员表和std::set的定义



c stl使用红色树木将数据存储在std::setstd::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必须实现诸如inserterase之类的操作,该操作要求Red-Black树的非const迭代器。SGI STL使用C风格的演员来执行此操作:

void erase(iterator __position) { 
  typedef typename _Rep_type::iterator _Rep_iterator;
  _M_t.erase((_Rep_iterator&)__position); 
}

我想知道:

  1. 为什么这个铸件安全?它将_Rep_type::const_iterator铸造为_Rep_type::iterator&
  2. 如何用C 样式写演员?我已经尝试这样做:static_castconst_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*>;

因此,对于您的问题:

  1. 这是安全的,因为两种类型具有完全相同的内存布局。
  2. 您不能使用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])

  1. const_cast
  2. static_cast
  3. static_cast后跟const_cast
  4. reinterpret_cast
  5. 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))

最新更新