Skip to content

Commit

Permalink
<functional>: Make default_searcher ADL-proof (#4379)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <[email protected]>
  • Loading branch information
frederick-vs-ja and StephanTLavavej authored Feb 13, 2024
1 parent 6682109 commit c674bcb
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 40 deletions.
80 changes: 40 additions & 40 deletions stl/inc/functional
Original file line number Diff line number Diff line change
Expand Up @@ -2484,21 +2484,21 @@ public:
_CONSTEXPR20 default_searcher(_FwdItPat _First, _FwdItPat _Last, _Pred_eq _Eq = _Pred_eq())
: _Data{_One_then_variadic_args_t{}, _STD move(_Eq), pair<_FwdItPat, _FwdItPat>{_First, _Last}} {
const auto& _Pat = _Data._Myval2;
_Adl_verify_range(_Pat.first, _Pat.second);
_STD _Adl_verify_range(_Pat.first, _Pat.second);
}

template <class _FwdItHaystack>
_NODISCARD _CONSTEXPR20 pair<_FwdItHaystack, _FwdItHaystack> operator()(
_FwdItHaystack _First, _FwdItHaystack _Last) const {
// search [_First, _Last) for the searcher's pattern
_Adl_verify_range(_First, _Last);
_STD _Adl_verify_range(_First, _Last);
const auto& _Eq = _Data._Get_first();
const auto& _Pat = _Data._Myval2;
_Adl_verify_range(_Pat.first, _Pat.second); // check again to ensure container is not destroyed
const auto _Result = _Search_pair_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last),
_Get_unwrapped(_Pat.first), _Get_unwrapped(_Pat.second), _Eq);
_Seek_wrapped(_Last, _Result.second);
_Seek_wrapped(_First, _Result.first);
_STD _Adl_verify_range(_Pat.first, _Pat.second); // check again to ensure container is not destroyed
const auto _Result = _STD _Search_pair_unchecked(_STD _Get_unwrapped(_First), _STD _Get_unwrapped(_Last),
_STD _Get_unwrapped(_Pat.first), _STD _Get_unwrapped(_Pat.second), _Eq);
_STD _Seek_wrapped(_Last, _Result.second);
_STD _Seek_wrapped(_First, _Result.first);
return {_First, _Last};
}

Expand Down Expand Up @@ -2678,15 +2678,15 @@ pair<_RanItHaystack, _RanItHaystack> _Boyer_moore_search(
static_assert(is_same_v<typename _Delta1_t::_Value_t, _Iter_value_t<_RanItHaystack>>,
"boyer_moore_searcher requires matching iterator value types");
using _Diff = typename _Delta1_t::_Diff;
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
_STD _Adl_verify_range(_First, _Last);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
const auto _Pat_size = _Delta1._Pat_size;
if (_Pat_size == 0) {
return {_First, _First};
}

const auto _UPat_first = _Get_unwrapped_n(_Delta1._Pat_first, _Pat_size);
const auto _UPat_first = _STD _Get_unwrapped_n(_Delta1._Pat_first, _Pat_size);
const auto _Eq = _Delta1._Get_eq();
_Diff _Shift = _Pat_size - 1;
while (_Shift < _ULast - _UFirst) {
Expand All @@ -2696,8 +2696,8 @@ pair<_RanItHaystack, _RanItHaystack> _Boyer_moore_search(
_Diff _Idx = _Pat_size - 1;
do {
if (_Idx == 0) {
_Seek_wrapped(_Last, _UFirst + _Pat_size);
_Seek_wrapped(_First, _UFirst);
_STD _Seek_wrapped(_Last, _UFirst + _Pat_size);
_STD _Seek_wrapped(_First, _UFirst);
return {_First, _Last};
}

Expand All @@ -2708,8 +2708,8 @@ pair<_RanItHaystack, _RanItHaystack> _Boyer_moore_search(
}
}

_Seek_wrapped(_Last, _ULast);
_Seek_wrapped(_First, _ULast);
_STD _Seek_wrapped(_Last, _ULast);
_STD _Seek_wrapped(_First, _ULast);
return {_First, _Last};
}

Expand All @@ -2719,34 +2719,34 @@ pair<_RanItHaystack, _RanItHaystack> _Boyer_moore_horspool_search(
static_assert(is_same_v<typename _Delta1_t::_Value_t, _Iter_value_t<_RanItHaystack>>,
"boyer_moore_horspool_searcher requires matching iterator value types");
using _Diff = typename _Delta1_t::_Diff;
_Adl_verify_range(_First, _Last);
_STD _Adl_verify_range(_First, _Last);
const auto _Pat_size = _Delta1._Pat_size;
if (_Pat_size == 0) {
return {_First, _First};
}

auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
const auto _UPat_first = _Get_unwrapped_n(_Delta1._Pat_first, _Pat_size);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
const auto _UPat_first = _STD _Get_unwrapped_n(_Delta1._Pat_first, _Pat_size);
const auto _Eq = _Delta1._Get_eq();
_Diff _Shift = _Pat_size - 1;
while (_Shift < _ULast - _UFirst) {
_UFirst += _Shift;
_Shift = _Delta1._Lookup(*_UFirst);
if (_Shift == 0) { // that is, *_UFirst == "_Pat.back()"
const auto _Candidate = _UFirst - (_Pat_size - 1);
if (_STD equal(_UPat_first, _UPat_first + (_Pat_size - 1), _Candidate, _Pass_fn(_Eq))) {
_Seek_wrapped(_Last, _Candidate + _Pat_size);
_Seek_wrapped(_First, _Candidate);
if (_STD equal(_UPat_first, _UPat_first + (_Pat_size - 1), _Candidate, _STD _Pass_fn(_Eq))) {
_STD _Seek_wrapped(_Last, _Candidate + _Pat_size);
_STD _Seek_wrapped(_First, _Candidate);
return {_First, _Last};
}

_Shift = 1;
}
}

_Seek_wrapped(_Last, _ULast);
_Seek_wrapped(_First, _ULast);
_STD _Seek_wrapped(_Last, _ULast);
_STD _Seek_wrapped(_First, _ULast);
return {_First, _Last};
}

Expand All @@ -2763,9 +2763,9 @@ struct _Single_delta1_type_boyer_moore_traits {
template <bool _Build_delta2>
static void* _Build_boyer_moore(_RanItPat _First, _RanItPat _Last, _Hash_ty _Hash_fn, _Pred_eq _Eq) {
// builds data tables for the Boyer-Moore string search algorithm
_Adl_verify_range(_First, _Last);
const auto _UFirst = _Get_unwrapped(_First);
const auto _Pat_size_raw = _Get_unwrapped(_Last) - _UFirst;
_STD _Adl_verify_range(_First, _Last);
const auto _UFirst = _STD _Get_unwrapped(_First);
const auto _Pat_size_raw = _STD _Get_unwrapped(_Last) - _UFirst;
using _CT = common_type_t<_Iter_diff_t<_RanItPat>, size_t>;
if (static_cast<_CT>(_Pat_size_raw) > static_cast<_CT>(SIZE_MAX)) {
_Xbad_alloc();
Expand All @@ -2784,7 +2784,7 @@ struct _Single_delta1_type_boyer_moore_traits {
*_Decode_aligned_block<_Atomic_counter_t>(_Buf) = 1;
void* const _Delta1 = _Decode_aligned_block<_Delta1_t>(_Buf);
if (_Build_delta2) {
_Build_boyer_moore_delta_2_table(
_STD _Build_boyer_moore_delta_2_table(
_Decode_aligned_block<_Diff>(_Buf, _Pat_size), _UFirst, _Pat_size_raw, _Eq);
}

Expand All @@ -2799,7 +2799,7 @@ struct _Single_delta1_type_boyer_moore_traits {
(void) _Decode_aligned_block<_Atomic_counter_t>(_Data);
const auto _Delta1 = _Decode_aligned_block<_Delta1_t>(_Data);
const auto _Delta2 = _Decode_aligned_block<_Diff>(_Data, static_cast<size_t>(_Delta1->_Pat_size));
return _Boyer_moore_search(*_Delta1, _Delta2, _First, _Last);
return _STD _Boyer_moore_search(*_Delta1, _Delta2, _First, _Last);
}

template <class _RanItHaystack>
Expand All @@ -2808,7 +2808,7 @@ struct _Single_delta1_type_boyer_moore_traits {
// decodes data tables for the Boyer-Moore string search algorithm
(void) _Decode_aligned_block<_Atomic_counter_t>(_Data);
const auto _Delta1 = _Decode_aligned_block<_Delta1_t>(_Data);
return _Boyer_moore_horspool_search(*_Delta1, _First, _Last);
return _STD _Boyer_moore_horspool_search(*_Delta1, _First, _Last);
}

static void _Destroy(void* const _Base) noexcept {
Expand Down Expand Up @@ -2841,9 +2841,9 @@ struct _Boyer_moore_traits_wchar_t_mode {
template <bool _Build_delta2>
static void* _Build_boyer_moore(_RanItPat _First, _RanItPat _Last, _Unused_parameter, _Unused_parameter) {
// builds data tables for the Boyer-Moore string search algorithm
_Adl_verify_range(_First, _Last);
const auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
_STD _Adl_verify_range(_First, _Last);
const auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
const auto _Pat_size_raw = _ULast - _UFirst;
using _CT = common_type_t<_Iter_diff_t<_RanItPat>, size_t>;
if (static_cast<_CT>(_Pat_size_raw) > static_cast<_CT>(SIZE_MAX)) {
Expand Down Expand Up @@ -2889,7 +2889,7 @@ struct _Boyer_moore_traits_wchar_t_mode {

if (_Build_delta2) {
equal_to<> _Eq;
_Build_boyer_moore_delta_2_table(
_STD _Build_boyer_moore_delta_2_table(
_Decode_aligned_block<_Diff>(_Buf, _Pat_size), _UFirst, _Pat_size_raw, _Eq);
}

Expand All @@ -2904,11 +2904,11 @@ struct _Boyer_moore_traits_wchar_t_mode {
if (*_Decode_aligned_block<bool>(_Data)) {
const auto _Delta1 = _Decode_aligned_block<_Big_table_t>(_Data);
const auto _Delta2 = _Decode_aligned_block<_Diff>(_Data, static_cast<size_t>(_Delta1->_Pat_size));
return _Boyer_moore_search(*_Delta1, _Delta2, _First, _Last);
return _STD _Boyer_moore_search(*_Delta1, _Delta2, _First, _Last);
} else {
const auto _Delta1 = _Decode_aligned_block<_Small_table_t>(_Data);
const auto _Delta2 = _Decode_aligned_block<_Diff>(_Data, static_cast<size_t>(_Delta1->_Pat_size));
return _Boyer_moore_search(*_Delta1, _Delta2, _First, _Last);
return _STD _Boyer_moore_search(*_Delta1, _Delta2, _First, _Last);
}
}

Expand All @@ -2919,10 +2919,10 @@ struct _Boyer_moore_traits_wchar_t_mode {
(void) _Decode_aligned_block<_Atomic_counter_t>(_Data);
if (*_Decode_aligned_block<bool>(_Data)) {
const auto _Delta1 = _Decode_aligned_block<_Big_table_t>(_Data);
return _Boyer_moore_horspool_search(*_Delta1, _First, _Last);
return _STD _Boyer_moore_horspool_search(*_Delta1, _First, _Last);
} else {
const auto _Delta1 = _Decode_aligned_block<_Small_table_t>(_Data);
return _Boyer_moore_horspool_search(*_Delta1, _First, _Last);
return _STD _Boyer_moore_horspool_search(*_Delta1, _First, _Last);
}
}

Expand Down Expand Up @@ -2977,7 +2977,7 @@ public:

boyer_moore_searcher& operator=(const boyer_moore_searcher& _Other) noexcept /* strengthened */ {
boyer_moore_searcher _Cpy(_Other);
swap(_Data, _Cpy._Data);
_STD swap(_Data, _Cpy._Data);
return *this;
}

Expand Down Expand Up @@ -3015,7 +3015,7 @@ public:

boyer_moore_horspool_searcher& operator=(const boyer_moore_horspool_searcher& _Other) noexcept /* strengthened */ {
boyer_moore_horspool_searcher _Cpy(_Other);
swap(_Data, _Cpy._Data);
_STD swap(_Data, _Cpy._Data);
return *this;
}

Expand Down
64 changes: 64 additions & 0 deletions tests/std/tests/P0220R1_searchers/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,70 @@ void test_case_randomized_cases() {
}
}

#ifndef _M_CEE // TRANSITION, VSO-1659496
template <class Tag, class T>
struct tagged_hash {
std::size_t operator()(const T& t) const {
return std::hash<T>{}(t);
}
};

template <class Tag>
struct tagged_equal {
template <class T, class U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) == std::forward<U>(u)) {
return std::forward<T>(t) == std::forward<U>(u);
}
};

template <class T>
struct holder {
T t;
};

struct incomplete;

template <class T>
using validating_hash = tagged_hash<holder<incomplete>, T>;

using validating_equal = tagged_equal<holder<incomplete>>;

void test_adl_proof_default_searcher_on_iterators() { // COMPILE-ONLY
using validator = holder<incomplete>*;
validator varr[1]{};
(void) std::search(varr, varr + 1, default_searcher<const validator*>{varr, varr + 1});
}

void test_adl_proof_default_searcher_on_functors() { // COMPILE-ONLY
char carr[1]{};
(void) std::search(carr, carr + 1, default_searcher<const char*, validating_equal>{carr, carr + 1});

wchar_t wcarr[1]{};
(void) std::search(wcarr, wcarr + 1, default_searcher<const wchar_t*, validating_equal>{wcarr, wcarr + 1});

int iarr[1]{};
(void) std::search(iarr, iarr + 1, default_searcher<const int*, validating_equal>{iarr, iarr + 1});
}

template <template <class RanIt, class Hash, class PredEq> class Searcher>
void test_adl_proof_searcher_on_functors() { // COMPILE-ONLY
char carr[1]{};
(void) std::search(carr, carr + 1, Searcher<const char*, validating_hash<char>, validating_equal>{carr, carr + 1});

wchar_t wcarr[1]{};
(void) std::search(
wcarr, wcarr + 1, Searcher<const wchar_t*, validating_hash<wchar_t>, validating_equal>{wcarr, wcarr + 1});

int iarr[1]{};
(void) std::search(iarr, iarr + 1, Searcher<const int*, validating_hash<int>, validating_equal>{iarr, iarr + 1});
}

void test_adl_proof_searcher_on_functors_all() { // COMPILE-ONLY
test_adl_proof_searcher_on_functors<boyer_moore_searcher>();
test_adl_proof_searcher_on_functors<boyer_moore_horspool_searcher>();
}
#endif // ^^^ no workaround ^^^

int main() {
test_boyer_moore_table2_construction();

Expand Down

0 comments on commit c674bcb

Please sign in to comment.