【发布时间】:2020-04-26 11:37:22
【问题描述】:
在整个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
}
【问题讨论】:
-
什么是
_Unwrapped()?我猜 MS 迭代器有一些与调试相关的包装器。 -
这不会引入开销 -- 我看到
constexpr,那么你指的是什么开销? -
@PaulMcKenzie 后一个版本不是 constexpr,如果它不可用的话。即使使用 constexpr 也会有更多的编译时间。也许我应该对我的措辞更加谨慎。我已经更新了这个问题,我主要只是对它为什么这样做感兴趣。
-
@IgorR。我放弃了这个,因为它有点像兔子洞,而且我没有足够的经验来说清楚。但是,是的,这是内置在迭代器中的,它似乎只是调用了 _Unfancy(),它返回了相应的指针。
-
@rustyx 我已经包含了它。
标签: c++ visual-c++ stl