Skip to content

<xutility>, <algorithm>: vector algorithms dispatching functions miss top level const on pointer parameters #4385

@AlexGuteniev

Description

@AlexGuteniev

The affected code

STL/stl/inc/algorithm

Lines 66 to 112 in bd3d740

_STD_BEGIN
template <class _Ty>
_STD pair<_Ty*, _Ty*> __std_minmax_element(_Ty* _First, _Ty* _Last) noexcept {
constexpr bool _Signed = _STD is_signed_v<_Ty>;
_Min_max_element_t _Res;
if constexpr (_STD is_same_v<_STD remove_const_t<_Ty>, float>) {
_Res = ::__std_minmax_element_f(_First, _Last, false);
} else if constexpr (_STD _Is_any_of_v<_STD remove_const_t<_Ty>, double, long double>) {
_Res = ::__std_minmax_element_d(_First, _Last, false);
} else if constexpr (sizeof(_Ty) == 1) {
_Res = ::__std_minmax_element_1(_First, _Last, _Signed);
} else if constexpr (sizeof(_Ty) == 2) {
_Res = ::__std_minmax_element_2(_First, _Last, _Signed);
} else if constexpr (sizeof(_Ty) == 4) {
_Res = ::__std_minmax_element_4(_First, _Last, _Signed);
} else if constexpr (sizeof(_Ty) == 8) {
_Res = ::__std_minmax_element_8(_First, _Last, _Signed);
} else {
static_assert(_STD _Always_false<_Ty>, "Unexpected size");
}
return {const_cast<_Ty*>(static_cast<const _Ty*>(_Res._Min)), const_cast<_Ty*>(static_cast<const _Ty*>(_Res._Max))};
}
template <class _Ty, class _TVal>
_Ty* __std_find_last_trivial(_Ty* _First, _Ty* _Last, const _TVal _Val) noexcept {
if constexpr (_STD is_pointer_v<_TVal> || _STD is_null_pointer_v<_TVal>) {
return _STD __std_find_last_trivial(_First, _Last, reinterpret_cast<uintptr_t>(_Val));
} else if constexpr (sizeof(_Ty) == 1) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_last_trivial_1(_First, _Last, static_cast<uint8_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 2) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_last_trivial_2(_First, _Last, static_cast<uint16_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 4) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_last_trivial_4(_First, _Last, static_cast<uint32_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 8) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_last_trivial_8(_First, _Last, static_cast<uint64_t>(_Val))));
} else {
static_assert(_STD _Always_false<_Ty>, "Unexpected size");
}
}
_STD_END

STL/stl/inc/xutility

Lines 113 to 214 in bd3d740

_STD_BEGIN
template <class _Ty, class _TVal>
__declspec(noalias) size_t __std_count_trivial(_Ty* _First, _Ty* _Last, const _TVal _Val) noexcept {
if constexpr (_STD is_pointer_v<_TVal> || _STD is_null_pointer_v<_TVal>) {
return _STD __std_count_trivial(_First, _Last, reinterpret_cast<uintptr_t>(_Val));
} else if constexpr (sizeof(_Ty) == 1) {
return ::__std_count_trivial_1(_First, _Last, static_cast<uint8_t>(_Val));
} else if constexpr (sizeof(_Ty) == 2) {
return ::__std_count_trivial_2(_First, _Last, static_cast<uint16_t>(_Val));
} else if constexpr (sizeof(_Ty) == 4) {
return ::__std_count_trivial_4(_First, _Last, static_cast<uint32_t>(_Val));
} else if constexpr (sizeof(_Ty) == 8) {
return ::__std_count_trivial_8(_First, _Last, static_cast<uint64_t>(_Val));
} else {
static_assert(_STD _Always_false<_Ty>, "Unexpected size");
}
}
template <class _Ty, class _TVal>
_Ty* __std_find_trivial(_Ty* _First, _Ty* _Last, const _TVal _Val) noexcept {
if constexpr (_STD is_pointer_v<_TVal> || _STD is_null_pointer_v<_TVal>) {
return _STD __std_find_trivial(_First, _Last, reinterpret_cast<uintptr_t>(_Val));
} else if constexpr (sizeof(_Ty) == 1) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_trivial_1(_First, _Last, static_cast<uint8_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 2) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_trivial_2(_First, _Last, static_cast<uint16_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 4) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_trivial_4(_First, _Last, static_cast<uint32_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 8) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_trivial_8(_First, _Last, static_cast<uint64_t>(_Val))));
} else {
static_assert(_STD _Always_false<_Ty>, "Unexpected size");
}
}
template <class _Ty, class _TVal>
_Ty* __std_find_trivial_unsized(_Ty* _First, const _TVal _Val) noexcept {
if constexpr (_STD is_pointer_v<_TVal> || _STD is_null_pointer_v<_TVal>) {
return _STD __std_find_trivial_unsized(_First, reinterpret_cast<uintptr_t>(_Val));
} else if constexpr (sizeof(_Ty) == 1) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_trivial_unsized_1(_First, static_cast<uint8_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 2) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_trivial_unsized_2(_First, static_cast<uint16_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 4) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_trivial_unsized_4(_First, static_cast<uint32_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 8) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_find_trivial_unsized_8(_First, static_cast<uint64_t>(_Val))));
} else {
static_assert(_STD _Always_false<_Ty>, "Unexpected size");
}
}
template <class _Ty>
_Ty* __std_min_element(_Ty* _First, _Ty* _Last) noexcept {
constexpr bool _Signed = _STD is_signed_v<_Ty>;
if constexpr (_STD is_same_v<_STD remove_const_t<_Ty>, float>) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_min_element_f(_First, _Last, false)));
} else if constexpr (_STD _Is_any_of_v<_STD remove_const_t<_Ty>, double, long double>) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_min_element_d(_First, _Last, false)));
} else if constexpr (sizeof(_Ty) == 1) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_min_element_1(_First, _Last, _Signed)));
} else if constexpr (sizeof(_Ty) == 2) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_min_element_2(_First, _Last, _Signed)));
} else if constexpr (sizeof(_Ty) == 4) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_min_element_4(_First, _Last, _Signed)));
} else if constexpr (sizeof(_Ty) == 8) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_min_element_8(_First, _Last, _Signed)));
} else {
static_assert(_STD _Always_false<_Ty>, "Unexpected size");
}
}
template <class _Ty>
_Ty* __std_max_element(_Ty* _First, _Ty* _Last) noexcept {
constexpr bool _Signed = _STD is_signed_v<_Ty>;
if constexpr (_STD is_same_v<_STD remove_const_t<_Ty>, float>) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_max_element_f(_First, _Last, false)));
} else if constexpr (_STD _Is_any_of_v<_STD remove_const_t<_Ty>, double, long double>) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_max_element_d(_First, _Last, false)));
} else if constexpr (sizeof(_Ty) == 1) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_max_element_1(_First, _Last, _Signed)));
} else if constexpr (sizeof(_Ty) == 2) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_max_element_2(_First, _Last, _Signed)));
} else if constexpr (sizeof(_Ty) == 4) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_max_element_4(_First, _Last, _Signed)));
} else if constexpr (sizeof(_Ty) == 8) {
return const_cast<_Ty*>(static_cast<const _Ty*>(::__std_max_element_8(_First, _Last, _Signed)));
} else {
static_assert(_STD _Always_false<_Ty>, "Unexpected size");
}
}
_STD_END

The desired change

The functions being defined here are taking _Ty* _First, _Ty* _Last parameters, but aren't modifying _First and _Last themselves. We should apply top-level const to these pointers, changing them to _Ty* const _First, _Ty* const _Last which will make our code more consistent and ever-so-slightly more resistant to mistakes.

Note that __std_find_trivial_unsized takes only _Ty* _First but should be changed similarly.

About this "good first issue"

This issue is intended for a new contributor (especially one new to GitHub) to get started with a simple change.

Please feel free to submit a pull request if there isn't one already linked here - no need to ask for permission! 😸

You can (and should) link your pull request to this issue using GitHub's close/fix/resolve syntax.
(in the PR description not the commit message)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementSomething can be improvedfixedSomething works now, yay!good first issueGood for newcomers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions