gpt4 book ai didi

c++ - 为什么 Microsoft Visual C++ 库实现 'unwrap' 迭代器?

转载 作者:行者123 更新时间:2023-12-02 10:03:23 25 4
gpt4 key购买 nike

贯穿microsofts stl implementation , 几乎所有的迭代器在使用前都被展开

例如,for_each看起来像这样:

template <class _InIt, class _Fn>
_Fn for_each(_InIt _First, _InIt _Last, _Fn _Func) { // perform function for each element [_First, _Last)
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst) {
_Func(*_UFirst);
}
return _Func; }

_Adl_verify_range 检查 first <= last ,我明白了,但我不太明白 _Get_unwrapped() 的目的:

#if _HAS_IF_CONSTEXPR
template <class _Iter>
_NODISCARD constexpr decltype(auto) _Get_unwrapped(_Iter&& _It) {
// unwrap an iterator previously subjected to _Adl_verify_range or otherwise validated
if constexpr (is_pointer_v<decay_t<_Iter>>) { // special-case pointers and arrays
return _It + 0;
} else if constexpr (_Unwrappable_v<_Iter>) {
return static_cast<_Iter&&>(_It)._Unwrapped();
} else {
return static_cast<_Iter&&>(_It);
}
}
#else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv
template <class _Iter, enable_if_t<_Unwrappable_v<_Iter>, int> = 0>
_NODISCARD constexpr decltype(auto) _Get_unwrapped(_Iter&& _It) {
// unwrap an iterator previously subjected to _Adl_verify_range or otherwise validated
return static_cast<_Iter&&>(_It)._Unwrapped();
}

它似乎想要衰减迭代器,或者将其转换为右值引用。

所以我的问题是为什么 Visual++ 使用这种范式?据我所知,GCC 不会这样做。

编辑

根据要求,来源iterator._Unwrapped()

_NODISCARD constexpr _Ptr _Unwrapped() const noexcept {
return _Myptr;
}

_Myptr 是在迭代器本身中定义的,只是一个原始指针:

template <class _Ptr>
class unchecked_array_iterator {
...
private:
_Ptr _Myptr; // underlying pointer
}

最佳答案

为什么 VC++ 包装迭代器?

这是一种设计选择。事实上,对于像 std::arraystd::vector 这样的类数组类型,迭代器可以是一个简单的 typedefT *,它很好地满足了迭代器语义,实际上这就是 GNU stdlibc++ 实现它的方式。但从标准的角度来看,iterator 是一个类指针 对象,但不一定是指针。所以……

  1. 假设它是一个指针将是一个错误,并可能导致不可移植的代码 (case in point)。
  2. 包装迭代器允许迭代器调试(参见 _ITERATOR_DEBUG_LEVEL )。例如,这里有一个调试 operator++:

    _CONSTEXPR17 _Array_const_iterator& operator++() {
    _STL_VERIFY(_Ptr, "cannot increment value-initialized array iterator");
    _STL_VERIFY(_Idx < _Size, "cannot increment array iterator past end");
    ++_Idx;
    return *this;
    }

为什么 VC++ 解包迭代器?

  1. 这是错误报告的优化。在像 std::for_each 这样的循环中,不是在 for_each 中间出现范围错误,而是在进入 for_each 时发出错误信号。

  2. 这是一种性能优化。

    • 在 Debug模式下,检查一次前提条件会导致更快的代码( Debug模式已经慢了 10 倍以上,因此即使在 Debug模式下性能仍然很重要)。
    • 在 Release模式下,编译器可以更好地优化指针访问,而不是每次都通过迭代器进行推断。是的,在大多数情况下它仍然可以推断出它,但是额外的间接级别可能会导致在代码的其他地方内联时做出不同的决策。

关于c++ - 为什么 Microsoft Visual C++ 库实现 'unwrap' 迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61440041/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com