Why does MSVC's STL implementation cast to const volatile char* here?

I was looking through some of the standard library's implementation for the usual containers (vector, unordered_map, etc...) when I came across the following, in the xutility header:

template <class _CtgIt, class _OutCtgIt>
_OutCtgIt _Copy_memmove(_CtgIt _First, _CtgIt _Last, _OutCtgIt _Dest) {
    auto _FirstPtr              = _To_address(_First);
    auto _LastPtr               = _To_address(_Last);
    auto _DestPtr               = _To_address(_Dest);
    const char* const _First_ch = const_cast<const char*>(reinterpret_cast<const volatile char*>(_FirstPtr));
    const char* const _Last_ch  = const_cast<const char*>(reinterpret_cast<const volatile char*>(_LastPtr));
    char* const _Dest_ch        = const_cast<char*>(reinterpret_cast<const volatile char*>(_DestPtr));
    const auto _Count           = static_cast<size_t>(_Last_ch - _First_ch);
    _CSTD memmove(_Dest_ch, _First_ch, _Count);
    if constexpr (is_pointer_v<_OutCtgIt>) {
        return reinterpret_cast<_OutCtgIt>(_Dest_ch + _Count);
    } else {
        return _Dest + (_LastPtr - _FirstPtr);
    }
}

Does anybody know why _First_ch and _Last_ch are first cast to const volatile char* type then immediately cast to const char*? I'm assuming it's to stop the compiler from optimizing prematurely, for some specific cases, but no concrete examples come to mind.


Solution 1:

If the target type of the pointer is volatile-qualified, it is not possible to use reinterpret_cast to directly cast to const char*.

reinterpret_cast is not allowed to cast away const or volatile. const_cast however can do this, while not being able to change the pointer's target type itself.

I think a C-style cast would also always work in this situation, but reasoning about it is a bit more difficult, since it attempts multiple C++-style conversion sequences, only the last of which is a reinterpret_cast followed by a const_cast.

It may be just a style choice to not use C-style casts here.