...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
"boost/poly_collection/exception.hpp"
synopsis"boost/poly_collection/base_collection_fwd.hpp"
synopsis"boost/poly_collection/base_collection.hpp"
synopsis"boost/poly_collection/function_collection_fwd.hpp"
synopsis"boost/poly_collection/function_collection.hpp"
synopsis"boost/poly_collection/any_collection_fwd.hpp"
synopsis"boost/poly_collection/any_collection.hpp"
synopsis"boost/poly_collection/algorithm.hpp"
synopsis
The key aspect of dynamic polymorphism is the ability for a value of type
T
to internally use another
value of a possibily different type U
for the implementation of a given interface. Base/derived polymorphism is
the classic model of dynamic polymorphism in C++, but not the only possible
one.
Formally, a polymorphism model is defined by
I
∈ Interface, the family Implementation(I
)
of types satisfying I
.
I
,
an operation subobject(x
) that maps each value of an implementation
type to its internally used value y
of a possibly different implementation type [22].
Static polymorphism is the trivial case where subobject(x
) = x
for all x
. Base/derived polymorphism
is characterized by:
Base
: std::is_polymorphic_v<Base>
}.
Base
)
= { Derived
: std::is_base_of_v<Base,Derived>
}.
x
)
= static_cast<Derived&>(x)
with typeid(x)==typeid(Derived)
.
A polymorphic container is an object that stores objects
of some type T
implementing
a given interface I
under
an implicitly associated polymorphism model. Polymorphic containers satisfy
the requirements for Container
and AllocatorAwareContainer
with the following modifications:
T
be CopyInsertable
,
CopyAssignable
,
MoveInsertable
,
MoveAssignable
or EqualityComparable
,
with the following semantic clause: may throw if some subobject in the
container is not CopyConstructible
(respectively, CopyAssignable
,
MoveConstructible
,
MoveAssignable
,
EqualityComparable
).
allocator_type
must have the property that for any type U
implementing I
and the
associated type A
=
std::allocator_traits<allocator_type>::rebind_alloc<U>
,
U
is CopyInsertable
(respectively MoveInsertable
)
with respect to A
if
and only if U
is CopyConstructible
(respectively MoveConstructible
);
all subobjects of type U
stored in these containers shall be constructed using the std::allocator_traits<A>::construct
function and destroyed using
the std::allocator_traits<A>::destroy
function; these functions (or
their equivalents for a rebound allocator) are called only for the types
of the stored subobjects, not for any other type (internal or public)
used by the container.
Polymorphic collections store their objects of type
value_type
in segments
dedicated to each of the types of the contained subojects. Only objects
whose subobjects are of an acceptable type are allowed,
where a type U
is said
to be acceptable if
MoveConstructible
,
MoveAssignable
or std::is_nothrow_move_constructible<U>::value
is true
.
Polymorphic collections conform to the requirements of PolymorphicContainer
with the following modfications and extra guarantees:
empty()
and size()
is linear on the number of segments
of the collection.
max_size()
is not provided.
a==b
evaluates to true
iff for each non-empty segment of subojects of type U
in a
there is a segment
of U
in b
with the same size and equal elements
in the same order, and vice versa.
CopyAssignable
,
MoveConstructible
or MoveAssignable
.
A type U
is said to be
registered into the collection if a (possibly empty)
segment for U
has been
created. Registered types continue to stay so for the duration of the container
except if it is moved from, assigned to, or swapped.
Each segment has an associated capacity indicating the maximum size that
it can attain without reallocation. When the limit is exceeded (or explicitly
through reserve
) new storage
space is allocated with greater capacity and elements are moved.
Collection traversal goes through the elements of the first segment, then the second, etc. The order in which segments are visited is unspecified but remains stable until a new segment is created.
Besides iterator
and const_iterator
, there are iterator types
local_base_iterator
and
local_iterator<U>
(and their const_
counterparts)
whose objects can be used to iterate over the segment for U
(in the same order followed by global
traversal). Local base iterators refer to value_type
,
whereas (const_
)local_iterator<U>
refers to U
. All local
iterators model RandomAccessIterator
.
Local base iterators may not be used to iterate across segments, and comparing
local base iterators associated to different segments is undefined behavior.
A (const) local base iterator to a segment for U
can be explicitly converted to (const_
)local_iterator<U>
pointing to the same position, and vice versa.
Insertion and erasure do not invalidate iterators (global or local) except those from the insertion/erasure point to the end of the affected segment, if its capacity is not exceeded, or all iterators/references to the segment otherwise [23].
For the description of the remaining requirements of polymorphic collections, we use the following notation:
C
is a polymorphic
collection type,
c
is an object of type
C
, cc
is a possibly const
object
of type C
,
al
is a value of type
C::allocator_type
,
info
is a const std::type_info&
,
U
is an acceptable
type, Us...
is a template parameter pack of acceptable types,
n
is a value of size_type
,
x
is a value of a type
T
implementing the
interface associated to the collection,
args...
is a function parameter pack of types Args&&...
,
it
is a possibly const
global iterator of c
,
it1
and it2
are (same-typed) possibly const
global iterators of a C
collection other than c
such that [it1
, it2
) is a valid range.
lbit
is a possibly
const local base iterator of c
,
lbit1
and lbit2
are (same-typed) possibly const
local base iterators of a C
collection other than c
such that [lbit1
,
lbit2
) is a valid range.
lit
is a (const_
)local_iterator<U>
of c
,
lit1
and lit2
are (same-typed) (const_
)local_iterator<U>
s of a C
collection other than c
such that [lit1
, lit2
) is a valid range,
i1
and i2
are iterators external to c
referring to T
such that [i1
, i2
) is a valid range,
j1
and j2
are iterators external to c
such that [j1
,
j2
) is a valid range,
xit1
and xit2
are (same-typed) possibly const
iterators (global or local) of c
such that [xit1
, xit2
) is a valid range.
RandomAccessIterator
with same value type, difference type and pointer and reference types
as C::iterator
, valid for accessing elements
of a given segment. Implicily convertible to C::const_local_base_iterator
,
explicitly convertible to C::local_iterator<U>
if the segment it points to is actually
that for U
.
RandomAccessIterator
with same value type, difference type and pointer and reference types
as C::const_iterator
, valid for accessing
elements of a given segment. Explicitly convertible to C::const_local_iterator<U>
if the segment it points to is actually that for U
.
RandomAccessIterator
with value type U
, reference
type U&
,
pointer type U*
and the same difference type as C::iterator
,
valid for accessing elements of the segment for U
.
Implicily convertible to C::const_local_iterator<U>
, explicitly convertible to C::local_base_iterator
.
RandomAccessIterator
with value type U
, reference
type const U&
, pointer type const
U*
and the same difference type as C::iterator
,
valid for accessing elements of the segment for U
.
Explicitly convertible to C::const_local_base_iterator
.
CopyConstructible
and CopyAssignable
type with information about a given segment of a collection. If ci
is a possibly const
object of type C::const_base_segment_info
associated
to the segment of c
for
U
, then
ci.begin()==c.cbegin(typeid(U))
ci.cbegin()==c.cbegin(typeid(U))
ci.begin<U>()==c.cbegin<U>()
ci.cbegin<U>()==c.cbegin<U>()
ci.end()==c.cend(typeid(U))
ci.cend()==c.cend(typeid(U))
ci.end<U>()==c.cend<U>()
ci.cend<U>()==c.cend<U>()
ci.type_info()==typeid(U)
CopyConstructible
and CopyAssignable
type publicly derived from C::const_base_segment_info
and exposing its public interface. Additionally, if i
is an object of type C::base_segment_info
associated to the segment of c
for U
, then
i.begin()==c.begin(typeid(U))
i.begin<U>()==c.begin<U>()
i.end()==c.end(typeid(U))
i.end<U>()==c.end<U>()
CopyConstructible
and CopyAssignable
type with information about the segment for U
.
If ci
is a possibly
const
object of type C::const_segment_info<U>
associated to the collection c
,
then
ci.begin()==c.cbegin<U>()
ci.cbegin()==c.cbegin<U>()
ci.end()==c.cend<U>()
ci.cend()==c.cend<U>()
CopyConstructible
and CopyAssignable
type publicly derived from C::const_segment_info<U>
and exposing its public interface.
Additionally, if i
is
an object of type C::segment_info<U>
associated to the collection c
,
then
i.begin()==c.begin<U>()
i.end()==c.end<U>()
InputIterator
with value type and reference type C::base_segment_info
.
C::const_base_segment_info_iterator
InputIterator
with value type and reference type C::const_base_segment_info
.
C::const_segment_traversal_info
CopyConstructible
and CopyAssignable
type with const
member functions
begin
/cbegin
and end
/cend
returning C::const_base_segment_info_iterator
objects that span over a range of C::const_base_segment_info
objects.
CopyConstructible
and CopyAssignable
type publicly derived from with C::const_segment_traversal_info
and exposing its public interface. Additionally, provides non-const member
functions begin
and
end
returning C::base_segment_info_iterator
objects
that span over an equivalent range of C::base_segment_info
objects.
Requires: C::allocator_type
is DefaultConstructible
.
[j1
, j2
)
can be inserted into C
.
Effects: Copy constructs the internal
allocator from C::allocator_type()
.
Internally calls this->insert(j1,j2)
on construction.
C(j1,j2,al)
C d(j1,j2,al)
Requires: [j1
,
j2
) can be inserted into
C
.
Effects:
Copy constructs the internal allocator from al
.
Internally calls this->insert(j1,j2)
on construction.
Effects: Registers (if needed) each of the indicated types in the collection.
cc.is_registered(info)
cc.is_registered<U>()
Returns: true
iff the indicated type is registered in the collection.
(1)
c.begin(info)
(2) c.begin<U>()
(3) const_cast<const C&>(c).begin(info)
(4) cc.cbegin(info)
(5) const_cast<const C&>(c).begin<U>()
(6) cc.cbegin<U>()
Returns: A local_base_iterator
(1) or local_iterator<U>
(2) or const_local_base_iterator
(3,4) or const_local_iterator<U>
(5,6) to the beginning of the segment
for the indicated type.
Throws:
If the indicated type is not registered.
(1)
c.end(info)
(2) c.end<U>()
(3) const_cast<const C&>(c).end(info)
(4) cc.cend(info)
(5) const_cast<const C&>(c).end<U>()
(6) cc.cend<U>()
Returns: A local_base_iterator
(1) or local_iterator<U>
(2) or const_local_base_iterator
(3,4) or const_local_iterator<U>
(5,6) to the end of the segment for
the indicated type.
Throws: If
the indicated type is not registered.
(1)
c.segment(info)
(2) c.segment<U>()
(3) const_cast<const C&>(c).segment(info)
(4) const_cast<const C&>(c).segment<U>()
Returns: A base_segment_info
(1) or segment_info<U>
(2) or const_base_segment_info
(3) or const_segment_info<U>
(4) object referring to the segment
for the indicated type.
Throws:
If the indicated type is not registered.
(1)
c.segment_traversal()
(2) const_cast<const C&>(c).segment_traversal()
Returns: A segment_traversal_info
(1) or const_segment_traversal_info
(2) object spanning over a range of segment descriptors for the collection.
The order in which segments are visited matches that of [c.begin()
,
c.end()
).
Returns: true
iff the segment for the indicated type exists and is empty.
Throws: If the indicated type is not registered.
Returns: The size of the segment for
the indicated type.
Throws: If
the indicated type is not registered.
cc.max_size(info)
cc.max_size<U>()
Returns: The maximum size attainable
by the segment for the indicated type.
Throws:
If the indicated type is not registered.
cc.capacity(info)
cc.capacity<U>()
Returns: The maximum size that the segment
for the indicated type can attain without requiring reallocation.
Throws: If the indicated type is not
registered.
Effects: Calls reserve
with n
for each of the
segments of the collection.
(1) c.reserve(info,n)
(2) c.reserve<U>(n)
Effects: Throws if the type indicated
by info
is not registered
(1) or registers U
if
needed (2). If n
is greater
than the current capacity of the segment for the indicated type, new
storage space is allocated with a capacity of at least n
and elements are moved there.
Complexity: Linear in the size of the
segment if reallocation happens, constant otherwise.
Throws: std::length_error
if n
is greater than
the return value of max_size
for the segment.
Effects: Calls shrink_to_fit
for each of the segments of the collection.
c.shrink_to_fit(info)
c.shrink_to_fit<U>()
Effects: Non-binding request to reduce
memory usage while preserving the sequence of elements of the segment
for the indicated type. May invalidate all iterators and references to
the segment.
Throws: If the indicated
type is not registered.
(1)
c.emplace<U>(args...)
(2) c.emplace_hint<U>(it,args...)
Requires: U
is constructible from std::forward<Args>(args)...
.
Effects:
Registers U
(if needed)
and inserts a new element with a subobject constructed from std::forward<Args>(args)...
:
(1) at the end of the segment for U
;
(2) just before the position indicated by it
,
if it points to the segment for U
,
or at the end of the segment for U
otherwise.
Returns: An iterator
to the newly inserted element.
Complexity: Amortized constant time
plus linear in the distance from the insertion position to the end of
the segment.
(1)
c.emplace_pos<U>(lbit,args...)
(2) c.emplace_pos(lit,args...)
Requires: U
is constructible from std::forward<Args>(args)...
. (1) lbit
points to the segment for U
.
Effects: Inserts a new element with
a subobject constructed from std::forward<Args>(args)...
just before the position indicated.
Returns: A local_base_iterator
(1) or local_iterator<U>
(2) to the newly inserted element.
Complexity: Amortized constant time
plus linear in the distance from the insertion position to the end of
the segment.
(1)
c.insert(x)
(2) c.insert(it,x)
Effects: Let Q
be the type of the subobject of x
.
If Q
= T
and T
is acceptable, registers T
if needed. If Q
= T
and T
is not acceptable, throws. If Q
≠ T
and Q
is not registered, throws. If x
is not a non-const rvalue expression
and Q
is not CopyConstructible
,
throws. Inserts an element with a subobject move constructed or copy
constructed from the subobject of x
:
(1) at the end of the corresponding segment; (2) just before the position
indicated by it
, if it
points to the corresponding segment, or at the end of the segment otherwise.
Returns: An iterator
to the newly inserted element.
Complexity:
Amortized constant time plus linear in the distance from the insertion
position to the end of the segment.
(1) c.insert(lbit,x)
(2) c.insert(lit,x)
Requires: The type of the subobject
of x
corresponds to the
indicated segment.
Effects: Inserts
an element with a subobject move constructed or copy constructed from
the subobject of x
just
before the position indicated.
Returns:
A local_base_iterator
(1) or local_iterator<U>
(2) to the newly inserted element.
Complexity: Amortized constant time
plus linear in the distance from the insertion position to the end of
the segment.
Effects: Equivalent to while(i1!=i2)c.insert(*i1++)
.
c.insert(it1,it2)
c.insert(lbit1,lbit2)
c.insert(lit1,lit2)
Effects: For each of the elements of the range in succession, registers the type of its subobject if needed and inserts it into the collection [24].
Effects: If it==c.end()
, equivalent to while(i1!=i2)c.insert(it,*i1++)
, otherwise inserts each of the elements
in [i1
, i2
) in succession with a hint pointing
to *it
[25].
c.insert(it,it1,it2)
c.insert(it,lbit1,lbit2)
c.insert(it,lit1,lit2)
Effects: If it==c.end()
, equivalent to the corresponding hint-less
version, otherwise for each of the elements in [i1
,
i2
) in succession registers
the type of its subobject if needed and inserts it into the collection
with a hint pointing to *it
[26].
c.insert(lbit,i1,i2)
Requires: The subojects of elements
in [i1
, i2
) are all of the type corresponding
to the indicated segment.
Effects:
Inserts a range of elements with subobjects copy constructed from those
in [i1
, i2
) just before lbit
.
Returns: A local_base_iterator
to the beginning of the inserted range.
c.insert(lit,j1,j2)
Requires: For each value x
in [j1
,
j2
) either (a) x
is of a type implementing the interface
associated to the collection and the subobject of x
is of type U
or (b)
U
is constructible from
x
.
Effects:
Inserts a range of elements with subobjects copy constructed (a) or constructed
(b) from the values in [j1
,
j2
) just before lit
.
Returns:
A local_iterator<U>
to the beginning of the inserted range.
c.erase(xit1)
c.erase(xit1,xit2)
Effects: Erases the indicated element(s).
Returns: A non-const iterator of the
same category as xit
pointing to the position just after the erased element(s).
Complexity: Linear on the number of elements erased
plus the distance from the last one to the end of its segment.
Effects: Erases all the elements of
the container.
Complexity: Linear.
c.clear(info)
c.clear<U>()
Effects: Erases all the elements of
the segment for the indicated type.
Complexity:
Linear in the size of the segment.
Throws:
If the indicated type is not registered.
All the collections in Boost.PolyCollection use the following exceptions (and only these) to signal various run-time problems with contained types:
namespace boost{ namespace poly_collection{ struct unregistered_type; struct not_copy_constructible; struct not_equality_comparable; } /* namespace poly_collection */ } /* namespace boost */
struct unregistered_type:std::logic_error { unregistered_type(const std::type_info& info); const std::type_info* pinfo; };
unregistered_type
is thrown
when an operation is requested on a type which does not yet have an associated
segment.
unregistered_type(const std::type_info& info);
Effects: Constructs an unregistered_type
object with the specified type information.
struct not_copy_constructible:std::logic_error { not_copy_constructible(const std::type_info& info); const std::type_info* pinfo; };
not_copy_constructible
is thrown when a copy operation is tried that involves a non-CopyConstructible
type.
not_copy_constructible(const std::type_info&
info);
Effects: Constructs a not_copy_constructible
object with the specified type information.
struct not_equality_comparable:std::logic_error { not_equality_comparable(const std::type_info& info); const std::type_info* pinfo; };
not_equality_comparable
is thrown when comparing two collections for (in)equality involves a non-EqualityComparable
type.
not_equality_comparable(const std::type_info&
info);
Effects: Constructs a not_equality_comparable
object with the specified type information.
#include <memory>
namespace boost{
namespace poly_collection{
template<typename Base,typename Allocator=std::allocator<Base>>
class base_collection
;
template<typename Base,typename Allocator>
bool operator==(
const base_collection<Base,Allocator>& x,
const base_collection<Base,Allocator>& y);
template<typename Base,typename Allocator>
bool operator!=(
const base_collection<Base,Allocator>& x,
const base_collection<Base,Allocator>& y);
template<typename Base,typename Allocator>
void swap(
base_collection<Base,Allocator>& x,base_collection<Base,Allocator>& y);
} /* namespace poly_collection */
using poly_collection::base_collection;
} /* namespace boost */
Forward declares the class template base_collection
and specifies its
default template arguments. Forward declares associated free functions and
brings boost::poly_collection::base_collection
to the boost
namespace.
#include <boost/poly_collection/base_collection_fwd.hpp>
namespace boost{
namespace poly_collection{
template<typename Base,typename Allocator>
class base_collection
;
template<typename Base,typename Allocator>
bool operator==(
const base_collection<Base,Allocator>& x,
const base_collection<Base,Allocator>& y);
template<typename Base,typename Allocator>
bool operator!=(
const base_collection<Base,Allocator>& x,
const base_collection<Base,Allocator>& y);
template<typename Base,typename Allocator>
void swap(
base_collection<Base,Allocator>& x,base_collection<Base,Allocator>& y);
} /* namespace poly_collection */
} /* namespace boost */
base_collection<Base,Allocator>
is a PolymorphicCollection
associated to the classic base/derived polymorphism
model:
Base
: std::is_polymorphic_v<Base>
}.
Base
)
= { Derived
: std::is_base_of_v<Base,Derived>
}.
x
)
= static_cast<Derived&>(x)
with typeid(x)==typeid(Derived)
.
template<typename Base,typename Allocator>
classbase_collection
{ public: // types: using value_type=Base
; using allocator_type=Allocator; using size_type=std::size_t; using difference_type=std::ptrdiff_t; using reference=value_type&; using const_reference=const value_type&; using pointer=typename std::allocator_traits<Allocator>::pointer; using const_pointer=typename std::allocator_traits<Allocator>::const_pointer; using iterator=implementation-defined; using const_iterator=implementation-defined; usinglocal_base_iterator
=implementation-defined; usingconst_local_base_iterator
=implementation-defined; template<typename T> usinglocal_iterator
=implementation-defined; template<typename T> usingconst_local_iterator
=implementation-defined; classconst_base_segment_info
; classbase_segment_info
; template<typename T> classconst_segment_info
; template<typename T> classsegment_info
; usingbase_segment_info_iterator
=implementation-defined; usingconst_base_segment_info_iterator
=implementation-defined; classconst_segment_traversal_info
; classsegment_traversal_info
; // construct/destroy/copy:base_collection
();base_collection
(constbase_collection
&);base_collection
(base_collection
&&); explicitbase_collection
(const allocator_type& al);base_collection
(constbase_collection
& x,const allocator_type& al);base_collection
(base_collection
&& x,const allocator_type& al); template<typename InputIterator>base_collection
( InputIterator first,InputIterator last, const allocator_type& al=allocator_type{});base_collection
& operator=(constbase_collection
&);base_collection
& operator=(base_collection
&&); allocator_type get_allocator()const noexcept; // type registration: template<typename... T> voidregister_types
(); boolis_registered
(const std::type_info& info)const; template<typename T> boolis_registered
()const; // iterators: iteratorbegin
()noexcept; iteratorend
()noexcept; const_iteratorbegin
()const noexcept; const_iteratorend
()const noexcept; const_iteratorcbegin
()const noexcept; const_iteratorcend
()const noexcept; local_base_iteratorbegin
(const std::type_info& info); local_base_iteratorend
(const std::type_info& info); const_local_base_iteratorbegin
(const std::type_info& info)const; const_local_base_iteratorend
(const std::type_info& info)const; const_local_base_iteratorcbegin
(const std::type_info& info)const; const_local_base_iteratorcend
(const std::type_info& info)const; template<typename T> local_iterator<T>begin
(); template<typename T> local_iterator<T>end
(); template<typename T> const_local_iterator<T>begin
()const; template<typename T> const_local_iterator<T>end
()const; template<typename T> const_local_iterator<T>cbegin
()const; template<typename T> const_local_iterator<T>cend
()const; base_segment_infosegment
(const std::type_info& info); const_base_segment_infosegment
(const std::type_info& info)const; template<typename T> segment_info<T>segment
(); template<typename T> const_segment_info<T>segment
()const; segment_traversal_infosegment_traversal
()noexcept; const_segment_traversal_infosegment_traversal
()const noexcept; // capacity: bool empty()const noexcept; boolempty
(const std::type_info& info)const; template<typename T> boolempty
()const; size_type size()const noexcept; size_typesize
(const std::type_info& info)const; template<typename T> size_typesize
()const; size_typemax_size
(const std::type_info& info)const; template<typename T> size_typemax_size
()const; size_typecapacity
(const std::type_info& info)const; template<typename T> size_typecapacity
()const; voidreserve
(size_type n); voidreserve
(const std::type_info& info,size_type n); template<typename T>voidreserve
(size_type n); voidshrink_to_fit
(); voidshrink_to_fit
(const std::type_info& info); template<typename T> voidshrink_to_fit
(); // modifiers: template<typename T,typename... Args> iteratoremplace
(Args&&... args); template<typename T,typename... Args> iteratoremplace_hint
(const_iterator hint,Args&&... args); template<typename T,typename LocalIterator,typename... Args> autoemplace_pos
(LocalIterator pos,Args&&... args); template<typename T> iteratorinsert
(T&& x); template<typename CollectionIterator,typename T> autoinsert
(CollectionIterator hint,T&& x); template<typename InputIterator> voidinsert
(InputIterator first,InputIterator last); template<typename CollectionIterator,typename InputIterator> voidinsert
(CollectionIterator hint,InputIterator first,InputIterator last); template<typename CollectionIterator> autoerase
(CollectionIterator pos); template<typename CollectionIterator> autoerase
(CollectionIterator first,CollectionIterator last); voidclear
()noexcept; voidclear
(const std::type_info& info); template<typename T> voidclear
(); void swap(base_collection
& x); };
#include <memory> namespace boost{ namespace poly_collection{ template<typename Signature> usingfunction_collection_value_type
=implementation-defined; template< typename Signature, typename Allocator=std::allocator<function_collection_value_type<Signature>> > classfunction_collection
; template<typename Signature,typename Allocator> bool operator==( const function_collection<Signature,Allocator>& x, const function_collection<Signature,Allocator>& y); template<typename Signature,typename Allocator> bool operator!=( const function_collection<Signature,Allocator>& x, const function_collection<Signature,Allocator>& y); template<typename Signature,typename Allocator> void swap( function_collection<Signature,Allocator>& x, function_collection<Signature,Allocator>& y); } /* namespace poly_collection */ using poly_collection::function_collection; } /* namespace boost */
Defines the alias template function_collection_value_type
(the
actual type it refers to, though, is merely forward declared). Forward declares
the class template function_collection
and specifies
its default template arguments. Forward declares associated free functions
and brings boost::poly_collection::function_collection
to the boost
namespace.
#include <boost/poly_collection/function_collection_fwd.hpp> namespace boost{ namespace poly_collection{ // defines the typefunction_collection_value_type
refers to template<typename Signature,typename Allocator> classfunction_collection
; template<typename Signature,typename Allocator> bool operator==( const function_collection<Signature,Allocator>& x, const function_collection<Signature,Allocator>& y); template<typename Signature,typename Allocator> bool operator!=( const function_collection<Signature,Allocator>& x, const function_collection<Signature,Allocator>& y); template<typename Signature,typename Allocator> void swap( function_collection<Signature,Allocator>& x, function_collection<Signature,Allocator>& y); } /* namespace poly_collection */ } /* namespace boost */
function_collection_value_type<Signature>
is the value_type
of boost::function_collection<Signature,Allocator>
,
where Signature
must be
a type of the form R(Args...)
.
function_collection_value_type<Signature>
wraps a reference to an object modeling
Callable
for the given Signature
.
The interface provided partially replicates that of std::function
and adds some extra
facilities.
In what follows, the name function_collection_value_type_impl
is used just for explanatory purposes in place of the actual class template
name, which is implementation defined.
template<typename Signature> using function_collection_value_type= function_collection_value_type_impl<Signature>; template<typename Signature> class function_collection_value_type_impl; template<typename R,typename... Args> class function_collection_value_type_impl<R(Args...)> { public: explicit operator bool()const noexcept; R operator()(Args... args)const; const std::type_info& target_type()const noexcept; template<typename T> T* target()noexcept; template<typename T> const T* target()const noexcept; operator std::function<R(Args...)>()const noexcept; void* data()noexcept; const void* data()const noexcept; };
explicit operator
bool()const noexcept;
Returns: true
.
R operator()(Args... args)const;
Effects:
, where
f is the wrapped callable object.INVOKE
(f,std::forward<Args>(args)...,R)
Returns:
Nothing if R
is void
, otherwise the return value of
.
INVOKE
(f,std::forward<Args>(args)...,R)
const std::type_info& target_type()const noexcept;
Returns: typeid(T)
where T
is the type of
the wrapped callable object.
template<typename T> T* target()noexcept;
template<typename T> const T* target()const noexcept;
Returns: If target_type()==typeid(T)
a pointer to the wrapped callable object, otherwise nullptr
.
operator std::function<R(Args...)>()const
noexcept;
Returns: A std::function<R(Args...)>
object holding a reference to the
wrapped callable object.
void* data()noexcept;
const
void*
data()const noexcept;
Returns: The address of the wrapped callable object.
function_collection<Signature,Allocator>
is a PolymorphicCollection
associated to a dynamic polymorphism
model based on call signature compatibility:
Signature
: Signature
= R(Args...)
}.
Signature
)
= { Callable
: std::is_invocable_r_v<R,Callable,Args...>
}.
x
)
=x.target<T>()
with typeid(T)==x.target_type()
,
if x
is an instantiation
of function_collection_value_type
,x
, otherwise.
template<typename Signature,typename Allocator>
classfunction_collection
{ public: // types: using value_type=; using allocator_type=Allocator; using size_type=std::size_t; using difference_type=std::ptrdiff_t; using reference=value_type&; using const_reference=const value_type&; using pointer=typename std::allocator_traits<Allocator>::pointer; using const_pointer=typename std::allocator_traits<Allocator>::const_pointer; using iterator=implementation-defined; using const_iterator=implementation-defined; using
function_collection_value_type
<Signature>local_base_iterator
=implementation-defined; usingconst_local_base_iterator
=implementation-defined; template<typename T> usinglocal_iterator
=implementation-defined; template<typename T> usingconst_local_iterator
=implementation-defined; classconst_base_segment_info
; classbase_segment_info
; template<typename T> classconst_segment_info
; template<typename T> classsegment_info
; usingbase_segment_info_iterator
=implementation-defined; usingconst_base_segment_info_iterator
=implementation-defined; classconst_segment_traversal_info
; classsegment_traversal_info
; // construct/destroy/copy:function_collection
();function_collection
(constfunction_collection
&);function_collection
(function_collection
&&); explicitfunction_collection
(const allocator_type& al);function_collection
(constfunction_collection
& x,const allocator_type& al);function_collection
(function_collection
&& x,const allocator_type& al); template<typename InputIterator>function_collection
( InputIterator first,InputIterator last, const allocator_type& al=allocator_type{});function_collection
& operator=(constfunction_collection
&);function_collection
& operator=(function_collection
&&); allocator_type get_allocator()const noexcept; // type registration: template<typename... T> voidregister_types
(); boolis_registered
(const std::type_info& info)const; template<typename T> boolis_registered
()const; // iterators: iteratorbegin
()noexcept; iteratorend
()noexcept; const_iteratorbegin
()const noexcept; const_iteratorend
()const noexcept; const_iteratorcbegin
()const noexcept; const_iteratorcend
()const noexcept; local_base_iteratorbegin
(const std::type_info& info); local_base_iteratorend
(const std::type_info& info); const_local_base_iteratorbegin
(const std::type_info& info)const; const_local_base_iteratorend
(const std::type_info& info)const; const_local_base_iteratorcbegin
(const std::type_info& info)const; const_local_base_iteratorcend
(const std::type_info& info)const; template<typename T> local_iterator<T>begin
(); template<typename T> local_iterator<T>end
(); template<typename T> const_local_iterator<T>begin
()const; template<typename T> const_local_iterator<T>end
()const; template<typename T> const_local_iterator<T>cbegin
()const; template<typename T> const_local_iterator<T>cend
()const; base_segment_infosegment
(const std::type_info& info); const_base_segment_infosegment
(const std::type_info& info)const; template<typename T> segment_info<T>segment
(); template<typename T> const_segment_info<T>segment
()const; segment_traversal_infosegment_traversal
()noexcept; const_segment_traversal_infosegment_traversal
()const noexcept; // capacity: bool empty()const noexcept; boolempty
(const std::type_info& info)const; template<typename T> boolempty
()const; size_type size()const noexcept; size_typesize
(const std::type_info& info)const; template<typename T> size_typesize
()const; size_typemax_size
(const std::type_info& info)const; template<typename T> size_typemax_size
()const; size_typecapacity
(const std::type_info& info)const; template<typename T> size_typecapacity
()const; voidreserve
(size_type n); voidreserve
(const std::type_info& info,size_type n); template<typename T>voidreserve
(size_type n); voidshrink_to_fit
(); voidshrink_to_fit
(const std::type_info& info); template<typename T> voidshrink_to_fit
(); // modifiers: template<typename T,typename... Args> iteratoremplace
(Args&&... args); template<typename T,typename... Args> iteratoremplace_hint
(const_iterator hint,Args&&... args); template<typename T,typename LocalIterator,typename... Args> autoemplace_pos
(LocalIterator pos,Args&&... args); template<typename T> iteratorinsert
(T&& x); template<typename CollectionIterator,typename T> autoinsert
(CollectionIterator hint,T&& x); template<typename InputIterator> voidinsert
(InputIterator first,InputIterator last); template<typename CollectionIterator,typename InputIterator> voidinsert
(CollectionIterator hint,InputIterator first,InputIterator last); template<typename CollectionIterator> autoerase
(CollectionIterator pos); template<typename CollectionIterator> autoerase
(CollectionIterator first,CollectionIterator last); voidclear
()noexcept; voidclear
(const std::type_info& info); template<typename T> voidclear
(); void swap(function_collection
& x); };
#include <memory> namespace boost{ namespace poly_collection{ template<typename Concept> usingany_collection_value_type
=implementation-defined; template< typename Concept, typename Allocator=std::allocator<any_collection_value_type<Concept>> > classany_collection
; template<typename Concept,typename Allocator> bool operator==( const any_collection<Concept,Allocator>& x, const any_collection<Concept,Allocator>& y); template<typename Concept,typename Allocator> bool operator!=( const any_collection<Concept,Allocator>& x, const any_collection<Concept,Allocator>& y); template<typename Concept,typename Allocator> void swap( any_collection<Concept,Allocator>& x,any_collection<Concept,Allocator>& y); } /* namespace poly_collection */ using poly_collection::any_collection; } /* namespace boost */
Defines the alias template any_collection_value_type
(the actual
type it refers to, though, is merely forward declared). Forward declares
the class template any_collection
and specifies its
default template arguments. Forward declares associated free functions and
brings boost::poly_collection::any_collection
to the boost
namespace.
#include <boost/poly_collection/any_collection_fwd.hpp> namespace boost{ namespace poly_collection{ // defines the typeany_collection_value_type
refers to template<typename Concept,typename Allocator> classany_collection
; template<typename Concept,typename Allocator> bool operator==( const any_collection<Concept,Allocator>& x, const any_collection<Concept,Allocator>& y); template<typename Concept,typename Allocator> bool operator!=( const any_collection<Concept,Allocator>& x, const any_collection<Concept,Allocator>& y); template<typename Concept,typename Allocator> void swap( any_collection<Concept,Allocator>& x,any_collection<Concept,Allocator>& y); } /* namespace poly_collection */ } /* namespace boost */
any_collection_value_type<Concept>
is the value_type
of boost::any_collection<Concept,Allocator>
,
where Concept
is defined
according to the requisites
of Boost.TypeErasure using
_self
as its placeholder.
The alias template definition has the form
template<typename Concept> using any_collection_value_type= boost::type_erasure::any<Concept2,boost::type_erasure::_self&>;
with boost::type_erasure::
is_subconcept
<Concept,Concept2>::value==true
. The exact definition of Concept2
is implementation defined.
any_collection<Concept,Allocator>
is a PolymorphicCollection
associated to a dynamic polymorphism
model based on duck
typing as implemented by Boost.TypeErasure:
Concept
: as specified
by Boost.TypeErasure,
using the _self
placeholder
}.
Concept
)
= { Concrete
: Concrete
satisfies Concept
}.
x
)
=boost::type_erasure::
any_cast
<T&>(x)
with typeid(T)==boost::type_erasure::
typeid_of
(x)
,
if x
is an instantiation
of boost::type_erasure::
any
including typeid_
<>
,x
, otherwise.
template<typename Concept,typename Allocator>
classany_collection
{ public: // types: using value_type=; using allocator_type=Allocator; using size_type=std::size_t; using difference_type=std::ptrdiff_t; using reference=value_type&; using const_reference=const value_type&; using pointer=typename std::allocator_traits<Allocator>::pointer; using const_pointer=typename std::allocator_traits<Allocator>::const_pointer; using iterator=implementation-defined; using const_iterator=implementation-defined; using
any_collection_value_type
<Concept>local_base_iterator
=implementation-defined; usingconst_local_base_iterator
=implementation-defined; template<typename T> usinglocal_iterator
=implementation-defined; template<typename T> usingconst_local_iterator
=implementation-defined; classconst_base_segment_info
; classbase_segment_info
; template<typename T> classconst_segment_info
; template<typename T> classsegment_info
; usingbase_segment_info_iterator
=implementation-defined; usingconst_base_segment_info_iterator
=implementation-defined; classconst_segment_traversal_info
; classsegment_traversal_info
; // construct/destroy/copy:any_collection
();any_collection
(constany_collection
&);any_collection
(any_collection
&&); explicitany_collection
(const allocator_type& al);any_collection
(constany_collection
& x,const allocator_type& al);any_collection
(any_collection
&& x,const allocator_type& al); template<typename InputIterator>any_collection
( InputIterator first,InputIterator last, const allocator_type& al=allocator_type{});any_collection
& operator=(constany_collection
&);any_collection
& operator=(any_collection
&&); allocator_type get_allocator()const noexcept; // type registration: template<typename... T> voidregister_types
(); boolis_registered
(const std::type_info& info)const; template<typename T> boolis_registered
()const; // iterators: iteratorbegin
()noexcept; iteratorend
()noexcept; const_iteratorbegin
()const noexcept; const_iteratorend
()const noexcept; const_iteratorcbegin
()const noexcept; const_iteratorcend
()const noexcept; local_base_iteratorbegin
(const std::type_info& info); local_base_iteratorend
(const std::type_info& info); const_local_base_iteratorbegin
(const std::type_info& info)const; const_local_base_iteratorend
(const std::type_info& info)const; const_local_base_iteratorcbegin
(const std::type_info& info)const; const_local_base_iteratorcend
(const std::type_info& info)const; template<typename T> local_iterator<T>begin
(); template<typename T> local_iterator<T>end
(); template<typename T> const_local_iterator<T>begin
()const; template<typename T> const_local_iterator<T>end
()const; template<typename T> const_local_iterator<T>cbegin
()const; template<typename T> const_local_iterator<T>cend
()const; base_segment_infosegment
(const std::type_info& info); const_base_segment_infosegment
(const std::type_info& info)const; template<typename T> segment_info<T>segment
(); template<typename T> const_segment_info<T>segment
()const; segment_traversal_infosegment_traversal
()noexcept; const_segment_traversal_infosegment_traversal
()const noexcept; // capacity: bool empty()const noexcept; boolempty
(const std::type_info& info)const; template<typename T> boolempty
()const; size_type size()const noexcept; size_typesize
(const std::type_info& info)const; template<typename T> size_typesize
()const; size_typemax_size
(const std::type_info& info)const; template<typename T> size_typemax_size
()const; size_typecapacity
(const std::type_info& info)const; template<typename T> size_typecapacity
()const; voidreserve
(size_type n); voidreserve
(const std::type_info& info,size_type n); template<typename T>voidreserve
(size_type n); voidshrink_to_fit
(); voidshrink_to_fit
(const std::type_info& info); template<typename T> voidshrink_to_fit
(); // modifiers: template<typename T,typename... Args> iteratoremplace
(Args&&... args); template<typename T,typename... Args> iteratoremplace_hint
(const_iterator hint,Args&&... args); template<typename T,typename LocalIterator,typename... Args> autoemplace_pos
(LocalIterator pos,Args&&... args); template<typename T> iteratorinsert
(T&& x); template<typename CollectionIterator,typename T> autoinsert
(CollectionIterator hint,T&& x); template<typename InputIterator> voidinsert
(InputIterator first,InputIterator last); template<typename CollectionIterator,typename InputIterator> voidinsert
(CollectionIterator hint,InputIterator first,InputIterator last); template<typename CollectionIterator> autoerase
(CollectionIterator pos); template<typename CollectionIterator> autoerase
(CollectionIterator first,CollectionIterator last); voidclear
()noexcept; voidclear
(const std::type_info& info); template<typename T> voidclear
(); void swap(any_collection
& x); };
namespace boost{ namespace poly_collection{// non-modifying sequence operations:
template<typename... Ts,typename PolyCollectionIterator,typename Predicate> bool all_of( PolyCollectionIterator first,PolyCollectionIterator last,Predicate pred); template<typename... Ts,typename PolyCollectionIterator,typename Predicate> bool any_of( PolyCollectionIterator first,PolyCollectionIterator last,Predicate pred); template<typename... Ts,typename PolyCollectionIterator,typename Predicate> bool none_of( PolyCollectionIterator first,PolyCollectionIterator last,Predicate pred); template<typename... Ts,typename PolyCollectionIterator,typename Function> Function for_each( PolyCollectionIterator first,PolyCollectionIterator last,Function f); template< typename... Ts,typename PolyCollectionIterator, typename Size,typename Function > Iterator for_each_n( PolyCollectionIterator first,Size n,Function f); template<typename... Ts,typename PolyCollectionIterator,typename T> PolyCollectionIterator find( PolyCollectionIterator first,PolyCollectionIterator last,const T& x); template<typename... Ts,typename PolyCollectionIterator,typename Predicate> PolyCollectionIterator find_if( PolyCollectionIterator first,PolyCollectionIterator last,Predicate pred); template<typename... Ts,typename PolyCollectionIterator,typename Predicate> PolyCollectionIterator find_if_not( PolyCollectionIterator first,PolyCollectionIterator last,Predicate pred); template< typename... Ts,typename PolyCollectionIterator,typename ForwardIterator > PolyCollectionIterator find_end( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2,ForwardIterator last2); template< typename... Ts,typename PolyCollectionIterator, typename ForwardIterator,typename BinaryPredicate > PolyCollectionIterator find_end( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred); template< typename... Ts,typename PolyCollectionIterator,typename ForwardIterator > PolyCollectionIterator find_first_of( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2,ForwardIterator last2); template< typename... Ts,typename PolyCollectionIterator, typename ForwardIterator,typename BinaryPredicate > PolyCollectionIterator find_first_of( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred); template<typename... Ts,typename PolyCollectionIterator> PolyCollectionIterator adjacent_find( PolyCollectionIterator first,PolyCollectionIterator last); template< typename... Ts,typename PolyCollectionIterator,typename BinaryPredicate > PolyCollectionIterator adjacent_find( PolyCollectionIterator first,PolyCollectionIterator last, BinaryPredicate pred); template<typename... Ts,typename PolyCollectionIterator,typename T> std::ptrdiff_t count( PolyCollectionIterator first,PolyCollectionIterator last,const T& x); template<typename... Ts,typename PolyCollectionIterator,typename Predicate> std::ptrdiff_t count_if( PolyCollectionIterator first,PolyCollectionIterator last,Predicate pred); template< typename... Ts,typename PolyCollectionIterator,typename InputIterator > std::pair<PolyCollectionIterator,InputIterator> mismatch( PolyCollectionIterator first1,PolyCollectionIterator last1, InputIterator first2); template< typename... Ts,typename PolyCollectionIterator, typename InputIterator,typename BinaryPredicate > std::pair<PolyCollectionIterator,InputIterator> mismatch( PolyCollectionIterator first1,PolyCollectionIterator last1, InputIterator first2,BinaryPredicate pred); template< typename... Ts,typename PolyCollectionIterator,typename InputIterator > std::pair<PolyCollectionIterator,InputIterator> mismatch( PolyCollectionIterator first1,PolyCollectionIterator last1, InputIterator first2,InputIterator last2); template< typename... Ts,typename PolyCollectionIterator, typename InputIterator,typename BinaryPredicate > std::pair<PolyCollectionIterator,InputIterator> mismatch( PolyCollectionIterator first1,PolyCollectionIterator last1, InputIterator first2,InputIterator last2,BinaryPredicate pred); template< typename... Ts,typename PolyCollectionIterator,typename InputIterator > bool equal( PolyCollectionIterator first1,PolyCollectionIterator last1, InputIterator first2); template< typename... Ts,typename PolyCollectionIterator, typename InputIterator,typename BinaryPredicate > bool equal( PolyCollectionIterator first1,PolyCollectionIterator last1, InputIterator first2,BinaryPredicate pred); template< typename... Ts,typename PolyCollectionIterator,typename InputIterator > bool equal( PolyCollectionIterator first1,PolyCollectionIterator last1, InputIterator first2,InputIterator last2); template< typename... Ts,typename PolyCollectionIterator, typename InputIterator,typename BinaryPredicate > bool equal( PolyCollectionIterator first1,PolyCollectionIterator last1, InputIterator first2,InputIterator last2,BinaryPredicate pred); template< typename... Ts,typename PolyCollectionIterator,typename ForwardIterator > bool is_permutation( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2); template< typename... Ts,typename PolyCollectionIterator, typename ForwardIterator,typename BinaryPredicate > bool is_permutation( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2,BinaryPredicate pred); template< typename... Ts,typename PolyCollectionIterator,typename ForwardIterator > bool is_permutation( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2,ForwardIterator last2); template< typename... Ts,typename PolyCollectionIterator, typename ForwardIterator,typename BinaryPredicate > bool is_permutation( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred); template< typename... Ts,typename PolyCollectionIterator,typename ForwardIterator > PolyCollectionIterator search( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2,ForwardIterator last2); template< typename... Ts,typename PolyCollectionIterator, typename ForwardIterator,typename BinaryPredicate > PolyCollectionIterator search( PolyCollectionIterator first1,PolyCollectionIterator last1, ForwardIterator first2,ForwardIterator last2,BinaryPredicate pred); template< typename... Ts,typename PolyCollectionIterator,typename Size,typename T > PolyCollectionIterator search_n( PolyCollectionIterator first1,PolyCollectionIterator last1, Size count,const T& x); template< typename... Ts,typename PolyCollectionIterator, typename Size,typename T,typename BinaryPredicate > PolyCollectionIterator search_n( PolyCollectionIterator first1,PolyCollectionIterator last1, Size count,const T& x,BinaryPredicate pred);// modifying sequence operations:
template< typename... Ts,typename PolyCollectionIterator,typename OutputIterator > OutputIterator copy( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res); template< typename... Ts,typename PolyCollectionIterator, typename Size,typename OutputIterator > OutputIterator copy_n( PolyCollectionIterator first,Size count,OutputIterator res); template< typename... Ts,typename PolyCollectionIterator, typename OutputIterator,typename Predicate > OutputIterator copy_if( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res,Predicate pred); template< typename... Ts,typename PolyCollectionIterator,typename OutputIterator > OutputIterator move( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res); template< typename... Ts,typename PolyCollectionIterator, typename OutputIterator,typename UnaryOperation > OutputIterator transform( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res,UnaryOperation op); template< typename... Ts,typename PolyCollectionIterator, typename InputIterator,typename OutputIterator,typename BinaryOperation > OutputIterator transform( PolyCollectionIterator first1,PolyCollectionIterator last1, InputIterator first2,OutputIterator res,BinaryOperation op); template< typename... Ts,typename PolyCollectionIterator, typename OutputIterator,typename T > OutputIterator replace_copy( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res,const T& old_x,const T& new_x); template< typename... Ts,typename PolyCollectionIterator, typename OutputIterator,typename Predicate,typename T > OutputIterator replace_copy_if( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res,Predicate pred,const T& new_x); template< typename... Ts,typename PolyCollectionIterator, typename OutputIterator,typename T > OutputIterator remove_copy( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res,const T& x); template< typename... Ts,typename PolyCollectionIterator, typename OutputIterator,typename Predicate > OutputIterator remove_copy_if( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res,Predicate pred); template< typename... Ts,typename PolyCollectionIterator,typename OutputIterator > OutputIterator unique_copy( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res); template< typename... Ts,typename PolyCollectionIterator, typename OutputIterator,typename BinaryPredicate > OutputIterator unique_copy( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res,BinaryPredicate pred); template< typename... Ts,typename PolyCollectionIterator,typename OutputIterator > OutputIterator rotate_copy( PolyCollectionIterator first,PolyCollectionIterator middle, PolyCollectionIterator last,OutputIterator res); template< typename... Ts,typename PolyCollectionIterator,typename OutputIterator, typename Distance,typename UniformRandomBitGenerator > OutputIterator sample( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator res,Distance n,UniformRandomBitGenerator&& g); template<typename... Ts,typename PolyCollectionIterator,typename Predicate> bool is_partitioned( PolyCollectionIterator first,PolyCollectionIterator last,Predicate pred); template< typename... Ts,typename PolyCollectionIterator, typename OutputIterator1,typename OutputIterator2,typename Predicate > std::pair<OutputIterator1,OutputIterator2> partition_copy( PolyCollectionIterator first,PolyCollectionIterator last, OutputIterator1 rest,OutputIterator2 resf,Predicate pred); template<typename... Ts,typename PolyCollectionIterator,typename Predicate> PolyCollectionIterator partition_point( PolyCollectionIterator first,PolyCollectionIterator last,Predicate pred); } /* namespace poly_collection */ } /* namespace boost */
The algorithms provided mimic the functionality of their homonyms in <algorithm>
but take advantage of the segmented nature of Boost.PolyCollection (global)
iterators to deliver better performance. Additionally, concrete types can
be passed to these algorithms for type restitution.
For the description of the algorithms we use the following notation:
alg
is the (unqualified) name of any of the algorithms in "boost/poly_collection/algorithm.hpp"
except copy_n
and rotate_copy
.
first
, middle
and last
are (same-typed) possibly const global iterators of a collection of Boost.PolyCollection
such that [first
, middle
) and [middle
,
last
) are valid ranges.
args...
is a function parameter pack of types Args&&...
,
Ts...
is a template parameter pack of arbitrary types.
(1) alg
(first,last,args...)
(2) for_each_n(first,args...)
(3) copy_n(first,args...)
(4) rotate_copy(first,middle,last,args...)
Requires: The expression expr
is well-formed, where expr
is defined as:
(1) std::
alg
(first,last,args...)
,
(2) std::for_each_n(first,args...)
,
(3) std::copy_n(first,args...)
,
(4) std::rotate_copy(first,middle,last,args...)
.
Effects:
Equivalent to expr
.
Returns: expr
.
Complexity: That of expr
.
(1) alg
<Ts...>(first,last,args...)
(2) for_each_n<Ts...>(first,args...)
(3) copy_n<Ts...>(first,args...)
(4) rotate_copy<Ts...>(first,middle,last,args...)
Requires: The expression expr
is well-formed, where expr
is defined as:
(1) std::
alg
(rfirst,rlast,args...)
,
(2) std::for_each_n(rfirst,args...)
,
(3) std::copy_n(rfirst,args...)
,
(4) std::rotate_copy(rfirst,rmiddle,rlast,args...)
,
and rfirst
, rmiddle
and rlast
are iterator-like objects behaving like their first
,
middle
and last
counterparts except that they dereference
to the corresponding subobject (const
)
T&
if pointing to a segment for T
and T
is in Ts...
[27].
Effects: Equivalent to
expr
.
Returns:
expr
.
Complexity:
That of expr
.
[22] This is a metalinguistic definition not directly expressible in C++. There are equivalent formulations that can indeed be realized in C++, but they add little to the comprehension of the concepts.
[23]
The global end()
iterator lies outside any segment, hence it always remain valid.
[24]
Note that, unlike c.insert(i1,i2)
, these versions do not throw due to
type registration problems.
[25]
That is, the hint remains stable even if it
may become invalid due to reallocations.
[26] The two previous notes apply here.
[27]
Strictly speaking a proper ForwardIterator
cannot behave like this as dereferencing must yield exactly
a (const
) value_type&
value, which disallows this type of
polymorphism.