在自定义容器上使用范围算法
Use ranged algorithm on custom container
我想升级我的自定义容器以兼容 std::ranges
算法,例如 find_if
和其他算法,例如下面的
auto is_satisfy = [](CustomContainer::value_type x) { ... };
std::ranges::find_if(custom_container, is_satisfy);
// instead of std::find_if(custom_container.begin(), custom_container.end(), is_satisfy);
std::ranges::find_if
的签名就像
struct find_if_fn {
template< ranges::input_range R,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>,
Proj>> Pred >
constexpr ranges::borrowed_iterator_t<R>
operator()( R&& r, Pred pred = {}, Proj proj = {} ) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
}
};
什么是 input_range concept 以及我自己的自定义容器如何支持此功能?
What is the input_range concept
是这样的:
template<class T>
concept input_range =
range<T> && input_iterator<iterator_t<T>>;
在英语中,input_range 是迭代器为 input_iterator 的范围。另一方面,范围概念是:
The range concept defines the requirements of a type that allows iteration over its elements by providing an iterator and sentinel that denote the elements of the range.
template<class T>
concept range =
requires(T& t) {
ranges::begin(t); // sometimes equality-preserving
ranges::end(t);
};
而input_iterator是:
The input_iterator concept defines requirements for a type whose
referenced values can be read (from the requirement for
indirectly_readable ([iterator.concept.readable])) and which can be
both pre- and post-incremented. [Note 1: Unlike the Cpp17InputIterator
requirements ([input.iterators]), the input_iterator concept does not
need equality comparison since iterators are typically compared to
sentinels. — end note]
template<class I>
concept input_iterator =
input_or_output_iterator<I> &&
indirectly_readable<I> &&
requires { typename ITER_CONCEPT(I); } &&
derived_from<ITER_CONCEPT(I), input_iterator_tag>;
您可以阅读依赖项概念、功能和特征的规范以了解确切的详细信息。
how this feature is supported by my own custom container?
简而言之:符合上述概念。
中级:提供成员函数 begin
和 end
其中前者应该 return 一个输入迭代器,后者应该 return 一个兼容的哨兵类型(可能是与迭代器类型相同或不同)。结束哨兵应该从一开始就可以到达,并且代表范围的最后一个元素。
一般来说,我建议查看 API 标准容器以了解它们提供的成员及其工作方式。将设计复制到您的自定义容器。
引用来自最新的标准草案。
我想升级我的自定义容器以兼容 std::ranges
算法,例如 find_if
和其他算法,例如下面的
auto is_satisfy = [](CustomContainer::value_type x) { ... };
std::ranges::find_if(custom_container, is_satisfy);
// instead of std::find_if(custom_container.begin(), custom_container.end(), is_satisfy);
std::ranges::find_if
的签名就像
struct find_if_fn {
template< ranges::input_range R,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>,
Proj>> Pred >
constexpr ranges::borrowed_iterator_t<R>
operator()( R&& r, Pred pred = {}, Proj proj = {} ) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
}
};
什么是 input_range concept 以及我自己的自定义容器如何支持此功能?
What is the input_range concept
是这样的:
template<class T> concept input_range = range<T> && input_iterator<iterator_t<T>>;
在英语中,input_range 是迭代器为 input_iterator 的范围。另一方面,范围概念是:
The range concept defines the requirements of a type that allows iteration over its elements by providing an iterator and sentinel that denote the elements of the range.
template<class T> concept range = requires(T& t) { ranges::begin(t); // sometimes equality-preserving ranges::end(t); };
而input_iterator是:
The input_iterator concept defines requirements for a type whose referenced values can be read (from the requirement for indirectly_readable ([iterator.concept.readable])) and which can be both pre- and post-incremented. [Note 1: Unlike the Cpp17InputIterator requirements ([input.iterators]), the input_iterator concept does not need equality comparison since iterators are typically compared to sentinels. — end note]
template<class I> concept input_iterator = input_or_output_iterator<I> && indirectly_readable<I> && requires { typename ITER_CONCEPT(I); } && derived_from<ITER_CONCEPT(I), input_iterator_tag>;
您可以阅读依赖项概念、功能和特征的规范以了解确切的详细信息。
how this feature is supported by my own custom container?
简而言之:符合上述概念。
中级:提供成员函数 begin
和 end
其中前者应该 return 一个输入迭代器,后者应该 return 一个兼容的哨兵类型(可能是与迭代器类型相同或不同)。结束哨兵应该从一开始就可以到达,并且代表范围的最后一个元素。
一般来说,我建议查看 API 标准容器以了解它们提供的成员及其工作方式。将设计复制到您的自定义容器。
引用来自最新的标准草案。