зеркало из https://github.com/microsoft/STL.git
Implement ranges::fill and ranges::fill_n (#904)
This commit is contained in:
Родитель
5e3423a377
Коммит
123b2b2bfa
|
@ -3003,6 +3003,85 @@ _FwdIt2 replace_copy_if(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _
|
|||
}
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
#ifdef __cpp_lib_concepts
|
||||
namespace ranges {
|
||||
// VARIABLE ranges::fill
|
||||
class _Fill_fn : private _Not_quite_object {
|
||||
public:
|
||||
using _Not_quite_object::_Not_quite_object;
|
||||
|
||||
template <class _Ty, output_iterator<const _Ty&> _It, sentinel_for<_It> _Se>
|
||||
constexpr _It operator()(_It _First, _Se _Last, const _Ty& _Value) const {
|
||||
_Adl_verify_range(_First, _Last);
|
||||
auto _UFirst = _Get_unwrapped(_STD move(_First));
|
||||
const auto _ULast = _Get_unwrapped(_STD move(_Last));
|
||||
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
if (!_STD is_constant_evaluated())
|
||||
#endif // __cpp_lib_is_constant_evaluated
|
||||
{
|
||||
const auto _Distance = static_cast<size_t>(_ULast - _UFirst);
|
||||
_CSTD memset(_UFirst, static_cast<unsigned char>(_Value), _Distance);
|
||||
_UFirst += _Distance;
|
||||
_Seek_wrapped(_First, _UFirst);
|
||||
return _First;
|
||||
}
|
||||
}
|
||||
|
||||
for (; _UFirst != _ULast; ++_UFirst) {
|
||||
*_UFirst = _Value;
|
||||
}
|
||||
|
||||
_Seek_wrapped(_First, _STD move(_UFirst));
|
||||
return _First;
|
||||
}
|
||||
|
||||
template <class _Ty, output_range<const _Ty&> _Rng>
|
||||
constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, const _Ty& _Value) const {
|
||||
auto _First = _RANGES begin(_Range);
|
||||
_Seek_wrapped(_First, (*this)(_Get_unwrapped(_STD move(_First)), _Uend(_Range), _Value));
|
||||
return _First;
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr _Fill_fn fill{_Not_quite_object::_Construct_tag{}};
|
||||
|
||||
// VARIABLE ranges::fill_n
|
||||
class _Fill_n_fn : private _Not_quite_object {
|
||||
public:
|
||||
using _Not_quite_object::_Not_quite_object;
|
||||
|
||||
template <class _Ty, output_iterator<const _Ty&> _It>
|
||||
constexpr _It operator()(_It _First, iter_difference_t<_It> _Count, const _Ty& _Value) const {
|
||||
if (_Count > 0) {
|
||||
auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count);
|
||||
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
if (!_STD is_constant_evaluated())
|
||||
#endif // __cpp_lib_is_constant_evaluated
|
||||
{
|
||||
_CSTD memset(_UFirst, static_cast<unsigned char>(_Value), static_cast<size_t>(_Count));
|
||||
_UFirst += _Count;
|
||||
_Seek_wrapped(_First, _UFirst); // no need to move since _UFirst is a pointer
|
||||
return _First;
|
||||
}
|
||||
}
|
||||
|
||||
for (; _Count > 0; ++_UFirst, (void) --_Count) {
|
||||
*_UFirst = _Value;
|
||||
}
|
||||
|
||||
_Seek_wrapped(_First, _STD move(_UFirst));
|
||||
}
|
||||
|
||||
return _First;
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr _Fill_n_fn fill_n{_Not_quite_object::_Construct_tag{}};
|
||||
} // namespace ranges
|
||||
#endif // __cpp_lib_concepts
|
||||
|
||||
// FUNCTION TEMPLATE generate
|
||||
template <class _FwdIt, class _Fn>
|
||||
_CONSTEXPR20 void generate(_FwdIt _First, _FwdIt _Last, _Fn _Func) { // replace [_First, _Last) with _Func()
|
||||
|
|
|
@ -807,6 +807,55 @@ struct with_input_ranges {
|
|||
}
|
||||
};
|
||||
|
||||
template <class Continuation, class Element = int>
|
||||
struct with_output_ranges {
|
||||
template <class... Args>
|
||||
static constexpr void call() {
|
||||
using namespace test;
|
||||
|
||||
// For all ranges, IsCommon implies Eq.
|
||||
// For single-pass ranges, Eq is uninteresting without IsCommon (there's only one valid iterator
|
||||
// value at a time, and no reason to compare it with itself for equality).
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::no, CanDifference::no, Common::no, CanCompare::no, ProxyRef::no>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::no, CanDifference::no, Common::no, CanCompare::no, ProxyRef::yes>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::no, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::no, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::yes>>();
|
||||
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::no, CanDifference::yes, Common::no, CanCompare::no, ProxyRef::no>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::no, CanDifference::yes, Common::no, CanCompare::no, ProxyRef::yes>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::no, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::no>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::no, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::yes>>();
|
||||
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::no, ProxyRef::no>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::no, ProxyRef::yes>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::yes>>();
|
||||
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::no, ProxyRef::no>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::no, ProxyRef::yes>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::no>>();
|
||||
Continuation::template call<Args...,
|
||||
range<output, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::yes>>();
|
||||
|
||||
with_forward_ranges<Continuation, Element>::template call<Args...>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Continuation, class Element = int>
|
||||
struct with_input_iterators {
|
||||
template <class... Args>
|
||||
|
@ -854,6 +903,11 @@ struct with_difference {
|
|||
}
|
||||
};
|
||||
|
||||
template <class Instantiator, class Element = int>
|
||||
constexpr void test_out() {
|
||||
with_output_ranges<Instantiator, Element>::call();
|
||||
}
|
||||
|
||||
template <class Instantiator, class Element = int>
|
||||
constexpr void test_in() {
|
||||
with_input_ranges<Instantiator, Element>::call();
|
||||
|
|
|
@ -245,6 +245,8 @@ tests\P0896R4_ranges_alg_copy_n
|
|||
tests\P0896R4_ranges_alg_count
|
||||
tests\P0896R4_ranges_alg_count_if
|
||||
tests\P0896R4_ranges_alg_equal
|
||||
tests\P0896R4_ranges_alg_fill
|
||||
tests\P0896R4_ranges_alg_fill_n
|
||||
tests\P0896R4_ranges_alg_find
|
||||
tests\P0896R4_ranges_alg_find_end
|
||||
tests\P0896R4_ranges_alg_find_first_of
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\concepts_matrix.lst
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
|
||||
#include <range_algorithm_support.hpp>
|
||||
|
||||
struct instantiator {
|
||||
template <class Out>
|
||||
static constexpr void call() {
|
||||
using ranges::fill;
|
||||
{
|
||||
int output[] = {13, 42, 1367};
|
||||
const int value = 7;
|
||||
auto result = fill(ranges::begin(output), ranges::end(output), value);
|
||||
for (const auto& elem : output) {
|
||||
assert(elem == value);
|
||||
}
|
||||
assert(result == ranges::end(output));
|
||||
}
|
||||
{ // Validate ranges overload
|
||||
int output[] = {13, 42, 1367};
|
||||
const int value = 13;
|
||||
auto result = fill(output, value);
|
||||
for (const auto& elem : output) {
|
||||
assert(elem == value);
|
||||
}
|
||||
assert(result == ranges::end(output));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
STATIC_ASSERT((test_out<instantiator>(), true));
|
||||
test_out<instantiator>();
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\concepts_matrix.lst
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
|
||||
#include <range_algorithm_support.hpp>
|
||||
|
||||
struct instantiator {
|
||||
template <class Out>
|
||||
static constexpr void call() {
|
||||
using ranges::fill_n;
|
||||
|
||||
const int expected_output[] = {13, 42, 1367};
|
||||
const int value = 7;
|
||||
{
|
||||
int output[] = {13, 42, 1367};
|
||||
auto result = fill_n(ranges::begin(output), ranges::distance(output), value);
|
||||
for (const auto& elem : output) {
|
||||
assert(elem == value);
|
||||
}
|
||||
assert(result == ranges::end(output));
|
||||
}
|
||||
{
|
||||
int output[] = {13, 42, 1367};
|
||||
auto result = fill_n(ranges::begin(output), 0, value);
|
||||
assert(ranges::equal(output, expected_output));
|
||||
assert(result == ranges::begin(output));
|
||||
}
|
||||
{
|
||||
int output[] = {13, 42, 1367};
|
||||
auto result = fill_n(ranges::begin(output), -1, value);
|
||||
assert(ranges::equal(output, expected_output));
|
||||
assert(result == ranges::begin(output));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
STATIC_ASSERT((test_out<instantiator>(), true));
|
||||
test_out<instantiator>();
|
||||
}
|
Загрузка…
Ссылка в новой задаче