贯穿microsofts stl implementation,在使用它们之前,几乎所有迭代器都是unwrapped。
例如,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
}
这似乎是一项优化功能;如果基础容器结构是数组,则将迭代器展开为指针。推测编译器比每次通过迭代器推断指针访问都能更好地优化指针访问。