JoeJ said:
There is no guarantee on STL specs, but using MSVC with default STL we get the following behavior in debug mode:
In MSVC on debug, specifically, yes, with iterator-debug level ≥ 1 at least:
_NODISCARD _CONSTEXPR20 _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ {
auto& _My_data = _Mypair._Myval2;
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(
_Pos < static_cast<size_type>(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return _My_data._Myfirst[_Pos];
}
I've personally disabled ITERATOR_DEBUG_LEVEL even in debug builds since its a real performance hog, especially with map/unordered_map (which is one of the few STL containers I still use), even for debug build levels. But yes, if he is using that setup, then it should work, but as with all undefined behaviour, its simply not a guarantee to even stay that way on MSVC, so one should at least be aware that even this assertion under those exact circumstances is not guaranteed to keep happening with future updates.
C-style array of course will never do anything useful on OOB under any circumstances, unless you offset it so far you reach into an inaccessible page. So you don't lose anything using std::array[i] over cArray[i] either.
JoeJ said:
Well, the reason you can't read the code is that it is so full of debug mode extra checks, the actual function is obfuscated.
Nah, that's not the reason why MSVC STL is hard to read, at least in my book. I've seen complex 2000 LoC and tons of debug-checks that are more readable than a single STL function. I personally attribute it to the weird and complicated camel_Snake_whateverthefuck naming, with leading _ on every variable and their mother; as well as overuse of macros. Isn't the following variant of the above operator[] 10 times more readable?
[[nodiscard]] constexpr ValueT& operator[](const size_type pos) noexcept /* strengthened */ {
auto& myData = myPair.myVal2;
if constexpr (CONTAINER_DEBUG_LEVEL > 0)
STL_VERIFY(pos < static_cast<size_type>(myData.myLast - myData.myfirst),
"vector subscript out of range");
return myData.myFirst[pos];
}
Does the same thing, uses the same variables, but way less verbose IMHO.