// bslstl_algorithm.h -*-C++-*- #ifndef INCLUDED_BSLSTL_ALGORITHM #define INCLUDED_BSLSTL_ALGORITHM #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide implementations for algorithms not in the system library. // //@CLASSES: // //@CANONICAL_HEADER: bsl_algorithm.h // //@SEE_ALSO: bsl+bslhdrs // //@DESCRIPTION: This component is for internal use only. Please include // '<bsl_algorithm.h>' instead. This component provides a namespace for // implementations for standard algorithms that are not provided by the // underlying standard library implementation. For example, 'any_of' is a // C++11 algorithm, and it is provided here for code using C++03. // ///Usage ///----- // This component is for use by the 'bsl+bslhdrs' package. Use // 'bsl_algorithm.h' directly. #include <bslscm_version.h> #include <bsls_assert.h> #include <bsls_keyword.h> #include <bsls_libraryfeatures.h> #include <bslstl_iterator.h> // iterator tags #include <bslstl_pair.h> #include <algorithm> #include <functional> // less #ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #include <bsls_nativestd.h> #endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES namespace BloombergLP { namespace bslstl { struct AlgorithmUtil { // Provide a namespace for implementing helper routines for algorithm // implementations. // CLASS FUNCTIONS template <class CONTAINER, class PREDICATE> static typename CONTAINER::size_type containerEraseIf(CONTAINER& container, PREDICATE predicate); // Erase all the elements in the specified container 'container' that // satisfy the specified predicate 'predicate'. Return the number of // elements erased. }; } // close package namespace } // close enterprise namespace namespace bsl { // Import selected symbols into bsl namespace using std::adjacent_find; using std::binary_search; using std::copy; using std::copy_backward; using std::equal; using std::equal_range; using std::fill; using std::fill_n; using std::find; using std::find_end; using std::find_first_of; using std::find_if; using std::for_each; using std::generate; using std::generate_n; using std::includes; using std::inplace_merge; using std::iter_swap; using std::lexicographical_compare; using std::lower_bound; using std::make_heap; using std::max; using std::max_element; using std::merge; using std::min; using std::min_element; using std::mismatch; using std::next_permutation; using std::nth_element; using std::partial_sort; using std::partial_sort_copy; using std::partition; using std::pop_heap; using std::prev_permutation; using std::push_heap; using std::remove; using std::remove_copy; using std::remove_copy_if; using std::remove_if; using std::replace; using std::replace_copy; using std::replace_copy_if; using std::replace_if; using std::reverse; using std::reverse_copy; using std::rotate; using std::rotate_copy; using std::search; using std::search_n; using std::set_difference; using std::set_intersection; using std::set_new_handler; using std::set_symmetric_difference; using std::set_union; using std::sort; using std::sort_heap; using std::stable_partition; using std::stable_sort; using std::swap; using std::swap_ranges; using std::transform; using std::unique; using std::unique_copy; using std::upper_bound; #if ! defined BSLS_LIBRARYFEATURES_HAS_CPP17_DEPRECATED_REMOVED // These names are removed by C++17 using std::random_shuffle; #endif #ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY using std::all_of; using std::any_of; using std::copy_if; // 'copy_n' is implemented separately in 'bslstp_exalgorithm' for backwards // compatibility with the previous STLport definition (which differs from // the platform implementation). // // using std::(copy_n); using std::find_if_not; using std::is_heap; using std::is_heap_until; using std::is_partitioned; using std::is_permutation; using std::is_sorted; using std::is_sorted_until; using std::minmax; using std::minmax_element; using std::move; using std::move_backward; using std::none_of; using std::partition_copy; using std::partition_point; using std::shuffle; #endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY // C++14 Algorithms // We get these via the "using std::equal" above // equal // mismatch #ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY using std::clamp; using std::for_each_n; using std::sample; #endif // BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY #ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES namespace ranges { // Non-modifying sequence operations using std::ranges::all_of; using std::ranges::any_of; using std::ranges::none_of; using std::ranges::for_each; using std::ranges::for_each_result; using std::ranges::for_each_n; using std::ranges::for_each_n_result; using std::ranges::count; using std::ranges::count_if; using std::ranges::mismatch; using std::ranges::mismatch_result; using std::ranges::equal; using std::ranges::lexicographical_compare; using std::ranges::find; using std::ranges::find_if; using std::ranges::find_if_not; using std::ranges::find_end; using std::ranges::find_first_of; using std::ranges::adjacent_find; using std::ranges::search; using std::ranges::search_n; // Modifying sequence operations using std::ranges::copy; using std::ranges::copy_result; using std::ranges::copy_if; using std::ranges::copy_if_result; using std::ranges::copy_n; using std::ranges::copy_n_result; using std::ranges::copy_backward; using std::ranges::copy_backward_result; using std::ranges::move; using std::ranges::move_result; using std::ranges::move_backward; using std::ranges::move_backward_result; using std::ranges::fill; using std::ranges::fill_n; using std::ranges::transform; using std::ranges::unary_transform_result; using std::ranges::binary_transform_result; using std::ranges::generate; using std::ranges::generate_n; using std::ranges::remove; using std::ranges::remove_if; using std::ranges::remove_copy; using std::ranges::remove_copy_result; using std::ranges::remove_copy_if; using std::ranges::remove_copy_if_result; using std::ranges::replace; using std::ranges::replace_if; using std::ranges::replace_copy; using std::ranges::replace_copy_result; using std::ranges::replace_copy_if; using std::ranges::replace_copy_if_result; using std::ranges::swap_ranges; using std::ranges::swap_ranges_result; using std::ranges::reverse; using std::ranges::reverse_copy; using std::ranges::reverse_copy_result; using std::ranges::rotate; using std::ranges::rotate_copy; using std::ranges::rotate_copy_result; using std::ranges::shuffle; using std::ranges::sample; using std::ranges::unique; using std::ranges::unique_copy; using std::ranges::unique_copy_result; // Partitioning operations using std::ranges::is_partitioned; using std::ranges::partition; using std::ranges::partition_copy; using std::ranges::partition_copy_result; using std::ranges::stable_partition; using std::ranges::partition_point; // Sorting operations using std::ranges::is_sorted; using std::ranges::is_sorted_until; using std::ranges::sort; using std::ranges::partial_sort; using std::ranges::partial_sort_copy; using std::ranges::stable_sort; using std::ranges::nth_element; // Binary search operations (on sorted ranges) using std::ranges::lower_bound; using std::ranges::upper_bound; using std::ranges::binary_search; using std::ranges::equal_range; // Other operations (on sorted ranges) using std::ranges::merge; using std::ranges::merge_result; using std::ranges::inplace_merge; // Set operations (on sorted ranges) using std::ranges::includes; using std::ranges::set_difference; using std::ranges::set_difference_result; using std::ranges::set_intersection; using std::ranges::set_intersection_result; using std::ranges::set_symmetric_difference; using std::ranges::set_symmetric_difference_result; using std::ranges::set_union; using std::ranges::set_union_result; // Heap operations using std::ranges::is_heap; using std::ranges::is_heap_until; using std::ranges::make_heap; using std::ranges::push_heap; using std::ranges::pop_heap; using std::ranges::sort_heap; // Minimum/maximum operations using std::ranges::max; using std::ranges::max_element; using std::ranges::min; using std::ranges::min_element; using std::ranges::minmax; using std::ranges::minmax_result; using std::ranges::minmax_element; using std::ranges::minmax_element_result; using std::ranges::clamp; using std::ranges::is_permutation; using std::ranges::next_permutation; using std::ranges::next_permutation_result; using std::ranges::prev_permutation; using std::ranges::prev_permutation_result; // Return types using std::ranges::in_fun_result; using std::ranges::in_in_result; using std::ranges::in_out_result; using std::ranges::in_in_out_result; using std::ranges::in_out_out_result; using std::ranges::min_max_result; using std::ranges::in_found_result; } #endif // BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES #ifndef BDE_OMIT_INTERNAL_DEPRECATED // Import additional names expected by existing code, but not mandated by // the standard header. using std::advance; using std::bad_alloc; using std::bidirectional_iterator_tag; using std::forward_iterator_tag; using std::input_iterator_tag; #if !defined(BSLS_PLATFORM_CMP_MSVC) && \ (BSLS_COMPILERFEATURES_CPLUSPLUS <= 201703L) using std::iterator; #endif using std::new_handler; using std::nothrow; using std::nothrow_t; using std::output_iterator_tag; using std::random_access_iterator_tag; #endif // BDE_OMIT_INTERNAL_DEPRECATED #ifndef BSLSTL_ITERATOR_PROVIDE_SUN_CPP98_FIXES // Use the compiler vendor supplied version of 'count' and 'count_if'. using std::count; using std::count_if; #else // Sun-specific fixes template <class InputIter, class TYPE> typename iterator_traits<InputIter>::difference_type count(InputIter first, InputIter last, const TYPE& value); // Provide an override for 'count' since Sun only provides a 4 argument // version while the C++ standard requires a 3 argument version. template <class InputIter, class PREDICATE> typename iterator_traits<InputIter>::difference_type count_if(InputIter first, InputIter last, PREDICATE pred); // Provide an override for 'count_if' since Sun only provides a 4 // argument version while the C++ standard requires a 3 argument // version. #endif // BSLSTL_ITERATOR_PROVIDE_SUN_CPP98_FIXES #ifndef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY template <class INPUT_ITERATOR, class PREDICATE> bool all_of(INPUT_ITERATOR first, INPUT_ITERATOR last, PREDICATE pred); // Return 'true' if, for the specified '[first, last)' range and the // specified predicate 'pred', the range is either empty or 'pred(*i)' // is 'true' for every iterator 'i' in the range, and 'false' // otherwise. Note that at most 'last - first' applications of the // predicate are performed. template <class INPUT_ITERATOR, class PREDICATE> bool any_of(INPUT_ITERATOR first, INPUT_ITERATOR last, PREDICATE pred); // Return 'false' if, for the specified '[first, last)' range and the // specified predicate 'pred', the range is either empty or 'pred(*i)' // is 'false' for every iterator 'i' in the range, and 'true' // otherwise. Note that at most 'last - first' applications of the // predicate are performed. template <class INPUT_ITERATOR, class PREDICATE> bool none_of(INPUT_ITERATOR first, INPUT_ITERATOR last, PREDICATE pred); // Return 'true' if, for the specified '[first, last)' range and the // specified predicate 'pred', the range is either empty or 'pred(*i)' // is 'false' for every iterator 'i' in the range, and 'false' // otherwise. Note that at most 'last - first' applications of the // predicate are performed. # if defined(BSLS_LIBRARYFEATURES_STDCPP_MSVC) // Visual Studio (the versions we support) provides 'copy_if'. using std::copy_if; # else # define BSLSTL_ALGORITHMWORKAROUND_IMPLEMENTS_COPY_IF 1 // C++03 standard libraries do not provide 'std::copy_if' (as it was not // part of the C++03 standard), but it is actually implementable in C++03, // so we inject it here. template <class INPUT_ITERATOR, class OUTPUT_ITERATOR, class PREDICATE> OUTPUT_ITERATOR copy_if(INPUT_ITERATOR first, INPUT_ITERATOR last, OUTPUT_ITERATOR result, PREDICATE pred); // Copy all elements in the half-open range of the specified 'first', // and 'last' ('[first, last)') input iterators for which the specified // 'pred' unary predicate is 'true' to the specified 'result' output // iterator, incrementing result after each copied element, keeping the // element order stable. The behavior is undefined if the ranges // '[first, last)' and // '[result, advance(result, distance(first, last)))' overlap. The // behavior is also undefined if 'pred' attempts to invoke any // non-constant functions of its argument. See also [alg.copy] in the // C++11 standard. # endif // !BSLS_LIBRARYFEATURES_STDCPP_MSVC #endif // !BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY #ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY template<class TYPE, class COMPARE> BSLS_KEYWORD_CONSTEXPR_CPP14 const TYPE& clamp(const TYPE& value, const TYPE& low, const TYPE& high, COMPARE comp); // Return the specified 'value' adjusted so that it is in the range // ['low', 'high'), using the specified comparison predicate 'comp'. template<class TYPE> BSLS_KEYWORD_CONSTEXPR_CPP14 const TYPE& clamp(const TYPE& value, const TYPE& low, const TYPE& high); // Return the specified 'value' adjusted so that it is in the range // ['low', 'high'). #endif #ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_OVERLOAD template<class FORWARD_ITERATOR, class SEARCHER> BSLS_KEYWORD_CONSTEXPR_CPP14 FORWARD_ITERATOR search(FORWARD_ITERATOR first, FORWARD_ITERATOR last, const SEARCHER& searcher); // Return the position in the specified range '[first, last)' of the // first occurrence of the pattern sought by the specified 'searcher' // if found, and 'last' otherwise. See [alg.search]. #endif // BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_OVERLOAD } // close namespace bsl // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // -------------------- // struct AlgorithmUtil // -------------------- template <class CONTAINER, class PREDICATE> inline typename CONTAINER::size_type BloombergLP::bslstl::AlgorithmUtil::containerEraseIf(CONTAINER& container, PREDICATE predicate) { typename CONTAINER::size_type oldSize = container.size(); for (typename CONTAINER::iterator it = container.begin(); it != container.end();) { if (predicate(*it)) { it = container.erase(it); } else { ++it; } } return oldSize - container.size(); } #ifdef BSLSTL_ITERATOR_PROVIDE_SUN_CPP98_FIXES template <class INPUT_ITERATOR, class TYPE> inline typename bsl::iterator_traits<INPUT_ITERATOR>::difference_type bsl::count(INPUT_ITERATOR first, INPUT_ITERATOR last, const TYPE& value) { typename bsl::iterator_traits<INPUT_ITERATOR>::difference_type ret = 0; std::count(first, last, value, ret); return ret; } template <class INPUT_ITERATOR, class PREDICATE> inline typename bsl::iterator_traits<INPUT_ITERATOR>::difference_type bsl::count_if(INPUT_ITERATOR first, INPUT_ITERATOR last, PREDICATE pred) { typename bsl::iterator_traits<INPUT_ITERATOR>::difference_type ret = 0; std::count_if(first, last, pred, ret); return ret; } #endif // BSLSTL_ITERATOR_PROVIDE_SUN_CPP98_FIXES #ifndef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY template <class INPUT_ITERATOR, class PREDICATE> bool bsl::all_of(INPUT_ITERATOR first, INPUT_ITERATOR last, PREDICATE pred) { for (; first != last; ++first) { if (!pred(*first)) { return false; // RETURN } } return true; } template <class INPUT_ITERATOR, class PREDICATE> bool bsl::any_of(INPUT_ITERATOR first, INPUT_ITERATOR last, PREDICATE pred) { for (; first != last; ++first) { if (pred(*first)) { return true; // RETURN } } return false; } template <class INPUT_ITERATOR, class PREDICATE> bool bsl::none_of(INPUT_ITERATOR first, INPUT_ITERATOR last, PREDICATE pred) { for (; first != last; ++first) { if (pred(*first)) { return false; // RETURN } } return true; } # ifdef BSLSTL_ALGORITHMWORKAROUND_IMPLEMENTS_COPY_IF template <class INPUT_ITERATOR, class OUTPUT_ITERATOR, class PREDICATE> inline OUTPUT_ITERATOR bsl::copy_if(INPUT_ITERATOR first, INPUT_ITERATOR last, OUTPUT_ITERATOR result, PREDICATE pred) { while(first != last) { if (pred(*first)) { *result++ = *first; } ++first; } return result; } # endif // BSLSTL_ALGORITHMWORKAROUND_IMPLEMENTS_COPY_IF #endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY #ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY template<class TYPE, class COMPARE> BSLS_KEYWORD_CONSTEXPR_CPP14 inline const TYPE& bsl::clamp(const TYPE& value, const TYPE& low, const TYPE& high, COMPARE comp) { BSLS_ASSERT(!comp(high, low)); return comp(value, low) ? low : comp(high, value) ? high : value; } template<class TYPE> BSLS_KEYWORD_CONSTEXPR_CPP14 inline const TYPE& bsl::clamp(const TYPE& value, const TYPE& low, const TYPE& high) { return bsl::clamp(value, low, high, std::less<TYPE>()); } #endif // BSLS_LIBRARYFEATURES_HAS_CPP17_BASELINE_LIBRARY #ifndef BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_OVERLOAD template<class FORWARD_ITERATOR, class SEARCHER> inline BSLS_KEYWORD_CONSTEXPR_CPP14 FORWARD_ITERATOR bsl::search(FORWARD_ITERATOR first, FORWARD_ITERATOR last, const SEARCHER& searcher) { bsl::pair<FORWARD_ITERATOR, FORWARD_ITERATOR> res = searcher(first, last); return res.first; } #endif // BSLS_LIBRARYFEATURES_HAS_CPP17_SEARCH_OVERLOAD #endif // INCLUDED_BSLSTL_ALGORITHM // ---------------------------------------------------------------------------- // Copyright 2020 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------