Meaning of _Get_unwrapped?

Viewed 240

I've been reading MS STL std::inner_product source and there seems to be a bit of usage of _Get_unwrapped, also on other places in the file. I managed to find the source of that thing but couldn't really decipher what does it do. What problem do I need to have to use such a thing? Is there maybe some kind of material that I can read about this kind of problem (or patterns)? I've pasted the code below for completeness' sake.

#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();
}

template <class _Iter, enable_if_t<!_Unwrappable_v<_Iter>, int> = 0>
_NODISCARD constexpr _Iter&& _Get_unwrapped(_Iter&& _It) {
    // (don't) unwrap an iterator previously subjected to _Adl_verify_range or otherwise validated
    return static_cast<_Iter&&>(_It);
}

template <class _Ty>
_NODISCARD constexpr _Ty* _Get_unwrapped(_Ty* const _Ptr) { // special case already-unwrapped pointers
    return _Ptr;
}
#endif // _HAS_IF_CONSTEXPR
1 Answers

but couldn't really decipher what does it do.

It does this:

  • If the class of the iterator argument is "unwrappable" (determined by the type trait _Unwrappable_v), then the function calls _Unwrapped member function of the iterator, and casts the result to rvalue reference to the iterator type and returns that.
  • Otherwise if the iterator is not a pointer, then it just casts the iterator itself to rvalue reference (which is essentially same as std::move) and returns that.
  • Otherwise the pointer is returned by value.

What problem do I need to have to use such a thing?

Given that the function is non-standard and not even publicly documented, you should only use it if you are implementing the MSVC C++ standard library.

Related