Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

Reference

Polymorphism models
Polymorphic containers
Header "boost/poly_collection/exception.hpp" synopsis
Header "boost/poly_collection/base_collection_fwd.hpp" synopsis
Header "boost/poly_collection/base_collection.hpp" synopsis
Header "boost/poly_collection/function_collection_fwd.hpp" synopsis
Header "boost/poly_collection/function_collection.hpp" synopsis
Header "boost/poly_collection/any_collection_fwd.hpp" synopsis
Header "boost/poly_collection/any_collection.hpp" synopsis
Header "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

  • A family Interface of permissible interface types and, for each IInterface, the family Implementation(I) of types satisfying I.
  • For a given interface type 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 [16].

Static polymorphism is the trivial case where subobject(x) = x for all x. Base/derived polymorphism is characterized by:

  • Interface = { Base : std::is_polymorphic_v<Base> }.
  • Implementation(Base) = { Derived : std::is_base_of_v<Base,Derived> }.
  • subobject(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:

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

Polymorphic collections conform to the requirements of PolymorphicContainer with the following modfications and extra guarantees:

  • The complexity of 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.
  • No exceptions are thrown associated to some subobject type not being 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 [17].

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.

C::local_base_iterator

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.

C::const_local_base_iterator

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.

C::local_iterator<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.

C::const_local_iterator<U>

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.

C::const_base_segment_info

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)

C::base_segment_info

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>()

C::const_segment_info<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>()

C::segment_info<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>()

C::base_segment_info_iterator

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.

C::segment_traversal_info

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.

C(j1,j2)
C d(j1,j2)

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.

c.register_types<Us...>()

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()).

cc.empty(info)
cc.empty<U>()

Returns: true iff the segment for the indicated type exists and is empty.
Throws: If the indicated type is not registered.

cc.size(info)
cc.size<U>()

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.

c.reserve(n)

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.

c.shrink_to_fit()

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 QT 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.

c.insert(i1,i2)

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 [18].

c.insert(it,i1,i2)

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 [19].

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 [20].

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.

c.clear()

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:

  • Interface = { Base : std::is_polymorphic_v<Base> }.
  • Implementation(Base) = { Derived : std::is_base_of_v<Base,Derived> }.
  • subobject(x) = static_cast<Derived&>(x) with typeid(x)==typeid(Derived).
template<typename Base,typename Allocator>
class base_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;
  using local_base_iterator=implementation-defined;
  using const_local_base_iterator=implementation-defined;
  template<typename T> using local_iterator=implementation-defined;
  template<typename T> using const_local_iterator=implementation-defined;
  class const_base_segment_info;
  class base_segment_info;
  template<typename T> class const_segment_info;
  template<typename T> class segment_info;
  using base_segment_info_iterator=implementation-defined;
  using const_base_segment_info_iterator=implementation-defined;
  class const_segment_traversal_info;
  class segment_traversal_info;

  // construct/destroy/copy:

  base_collection();
  base_collection(const base_collection&);
  base_collection(base_collection&&);
  explicit base_collection(const allocator_type& al);
  base_collection(const base_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=(const base_collection&);
  base_collection& operator=(base_collection&&);

  allocator_type get_allocator()const noexcept;

  // type registration:

  template<typename... T>
  void register_types();

  bool is_registered(const std::type_info& info)const;
  template<typename T> bool is_registered()const;

  // iterators:

  iterator       begin()noexcept;
  iterator       end()noexcept;
  const_iterator begin()const noexcept;
  const_iterator end()const noexcept;
  const_iterator cbegin()const noexcept;
  const_iterator cend()const noexcept;

  local_base_iterator begin(const std::type_info& info);
  local_base_iterator end(const std::type_info& info);
  const_local_base_iterator begin(const std::type_info& info)const;
  const_local_base_iterator end(const std::type_info& info)const;
  const_local_base_iterator cbegin(const std::type_info& info)const;
  const_local_base_iterator cend(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_info       segment(const std::type_info& info);
  const_base_segment_info segment(const std::type_info& info)const;
  template<typename T> segment_info<T>       segment();
  template<typename T> const_segment_info<T> segment()const;

  segment_traversal_info       segment_traversal()noexcept;
  const_segment_traversal_info segment_traversal()const noexcept;

  // capacity:

  bool empty()const noexcept;
  bool empty(const std::type_info& info)const;
  template<typename T> bool empty()const;

  size_type size()const noexcept;
  size_type size(const std::type_info& info)const;
  template<typename T> size_type size()const;

  size_type max_size(const std::type_info& info)const;
  template<typename T> size_type max_size()const;

  size_type capacity(const std::type_info& info)const;
  template<typename T> size_type capacity()const;

  void reserve(size_type n);
  void reserve(const std::type_info& info,size_type n);
  template<typename T>void reserve(size_type n);

  void shrink_to_fit();
  void shrink_to_fit(const std::type_info& info);
  template<typename T> void shrink_to_fit();

  // modifiers:

  template<typename T,typename... Args>
  iterator emplace(Args&&... args);

  template<typename T,typename... Args>
  iterator emplace_hint(const_iterator hint,Args&&... args);

  template<typename T,typename LocalIterator,typename... Args>
  auto emplace_pos(LocalIterator pos,Args&&... args);

  template<typename T>
  iterator insert(T&& x);

  template<typename CollectionIterator,typename T>
  auto insert(CollectionIterator hint,T&& x);

  template<typename InputIterator>
  void insert(InputIterator first,InputIterator last);

  template<typename CollectionIterator,typename InputIterator>
  void insert(CollectionIterator hint,InputIterator first,InputIterator last);

  template<typename CollectionIterator>
  auto erase(CollectionIterator pos);

  template<typename CollectionIterator>
  auto erase(CollectionIterator first,CollectionIterator last);

  void clear()noexcept;
  void clear(const std::type_info& info);
  template<typename T> void clear();

  void swap(base_collection& x);
};
#include <memory>

namespace boost{

namespace poly_collection{

template<typename Signature>
using function_collection_value_type=implementation-defined;

template<
  typename Signature,
  typename Allocator=std::allocator<function_collection_value_type<Signature>>
>
class function_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 type function_collection_value_type refers to

template<typename Signature,typename Allocator>
class function_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: INVOKE(f,std::forward<Args>(args)...,R), where f is the wrapped callable object.
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:

  • Interface = { Signature : Signature = R(Args...) }.
  • Implementation(Signature) = { Callable : std::is_invocable_r_v<R,Callable,Args...> }.
  • subobject(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>
class function_collection
{
public:
  // types:

  using value_type=function_collection_value_type<Signature>;
  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 local_base_iterator=implementation-defined;
  using const_local_base_iterator=implementation-defined;
  template<typename T> using local_iterator=implementation-defined;
  template<typename T> using const_local_iterator=implementation-defined;
  class const_base_segment_info;
  class base_segment_info;
  template<typename T> class const_segment_info;
  template<typename T> class segment_info;
  using base_segment_info_iterator=implementation-defined;
  using const_base_segment_info_iterator=implementation-defined;
  class const_segment_traversal_info;
  class segment_traversal_info;

  // construct/destroy/copy:

  function_collection();
  function_collection(const function_collection&);
  function_collection(function_collection&&);
  explicit function_collection(const allocator_type& al);
  function_collection(const function_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=(const function_collection&);
  function_collection& operator=(function_collection&&);

  allocator_type get_allocator()const noexcept;

  // type registration:

  template<typename... T>
  void register_types();

  bool is_registered(const std::type_info& info)const;
  template<typename T> bool is_registered()const;

  // iterators:

  iterator       begin()noexcept;
  iterator       end()noexcept;
  const_iterator begin()const noexcept;
  const_iterator end()const noexcept;
  const_iterator cbegin()const noexcept;
  const_iterator cend()const noexcept;

  local_base_iterator begin(const std::type_info& info);
  local_base_iterator end(const std::type_info& info);
  const_local_base_iterator begin(const std::type_info& info)const;
  const_local_base_iterator end(const std::type_info& info)const;
  const_local_base_iterator cbegin(const std::type_info& info)const;
  const_local_base_iterator cend(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_info       segment(const std::type_info& info);
  const_base_segment_info segment(const std::type_info& info)const;
  template<typename T> segment_info<T>       segment();
  template<typename T> const_segment_info<T> segment()const;

  segment_traversal_info       segment_traversal()noexcept;
  const_segment_traversal_info segment_traversal()const noexcept;

  // capacity:

  bool empty()const noexcept;
  bool empty(const std::type_info& info)const;
  template<typename T> bool empty()const;

  size_type size()const noexcept;
  size_type size(const std::type_info& info)const;
  template<typename T> size_type size()const;

  size_type max_size(const std::type_info& info)const;
  template<typename T> size_type max_size()const;

  size_type capacity(const std::type_info& info)const;
  template<typename T> size_type capacity()const;

  void reserve(size_type n);
  void reserve(const std::type_info& info,size_type n);
  template<typename T>void reserve(size_type n);

  void shrink_to_fit();
  void shrink_to_fit(const std::type_info& info);
  template<typename T> void shrink_to_fit();

  // modifiers:

  template<typename T,typename... Args>
  iterator emplace(Args&&... args);

  template<typename T,typename... Args>
  iterator emplace_hint(const_iterator hint,Args&&... args);

  template<typename T,typename LocalIterator,typename... Args>
  auto emplace_pos(LocalIterator pos,Args&&... args);

  template<typename T>
  iterator insert(T&& x);

  template<typename CollectionIterator,typename T>
  auto insert(CollectionIterator hint,T&& x);

  template<typename InputIterator>
  void insert(InputIterator first,InputIterator last);

  template<typename CollectionIterator,typename InputIterator>
  void insert(CollectionIterator hint,InputIterator first,InputIterator last);

  template<typename CollectionIterator>
  auto erase(CollectionIterator pos);

  template<typename CollectionIterator>
  auto erase(CollectionIterator first,CollectionIterator last);

  void clear()noexcept;
  void clear(const std::type_info& info);
  template<typename T> void clear();

  void swap(function_collection& x);
};
#include <memory>

namespace boost{

namespace poly_collection{

template<typename Concept>
using any_collection_value_type=implementation-defined;

template<
  typename Concept,
  typename Allocator=std::allocator<any_collection_value_type<Concept>>
>
class any_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 type any_collection_value_type refers to

template<typename Concept,typename Allocator>
class any_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:

  • Interface = { Concept : as specified by Boost.TypeErasure, using the _self placeholder }.
  • Implementation(Concept) = { Concrete : Concrete satisfies Concept }.
  • subobject(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>
class any_collection
{
public:
  // types:

  using value_type=any_collection_value_type<Concept>;
  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 local_base_iterator=implementation-defined;
  using const_local_base_iterator=implementation-defined;
  template<typename T> using local_iterator=implementation-defined;
  template<typename T> using const_local_iterator=implementation-defined;
  class const_base_segment_info;
  class base_segment_info;
  template<typename T> class const_segment_info;
  template<typename T> class segment_info;
  using base_segment_info_iterator=implementation-defined;
  using const_base_segment_info_iterator=implementation-defined;
  class const_segment_traversal_info;
  class segment_traversal_info;

  // construct/destroy/copy:

  any_collection();
  any_collection(const any_collection&);
  any_collection(any_collection&&);
  explicit any_collection(const allocator_type& al);
  any_collection(const any_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=(const any_collection&);
  any_collection& operator=(any_collection&&);

  allocator_type get_allocator()const noexcept;

  // type registration:

  template<typename... T>
  void register_types();

  bool is_registered(const std::type_info& info)const;
  template<typename T> bool is_registered()const;

  // iterators:

  iterator       begin()noexcept;
  iterator       end()noexcept;
  const_iterator begin()const noexcept;
  const_iterator end()const noexcept;
  const_iterator cbegin()const noexcept;
  const_iterator cend()const noexcept;

  local_base_iterator begin(const std::type_info& info);
  local_base_iterator end(const std::type_info& info);
  const_local_base_iterator begin(const std::type_info& info)const;
  const_local_base_iterator end(const std::type_info& info)const;
  const_local_base_iterator cbegin(const std::type_info& info)const;
  const_local_base_iterator cend(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_info       segment(const std::type_info& info);
  const_base_segment_info segment(const std::type_info& info)const;
  template<typename T> segment_info<T>       segment();
  template<typename T> const_segment_info<T> segment()const;

  segment_traversal_info       segment_traversal()noexcept;
  const_segment_traversal_info segment_traversal()const noexcept;

  // capacity:

  bool empty()const noexcept;
  bool empty(const std::type_info& info)const;
  template<typename T> bool empty()const;

  size_type size()const noexcept;
  size_type size(const std::type_info& info)const;
  template<typename T> size_type size()const;

  size_type max_size(const std::type_info& info)const;
  template<typename T> size_type max_size()const;

  size_type capacity(const std::type_info& info)const;
  template<typename T> size_type capacity()const;

  void reserve(size_type n);
  void reserve(const std::type_info& info,size_type n);
  template<typename T>void reserve(size_type n);

  void shrink_to_fit();
  void shrink_to_fit(const std::type_info& info);
  template<typename T> void shrink_to_fit();

  // modifiers:

  template<typename T,typename... Args>
  iterator emplace(Args&&... args);

  template<typename T,typename... Args>
  iterator emplace_hint(const_iterator hint,Args&&... args);

  template<typename T,typename LocalIterator,typename... Args>
  auto emplace_pos(LocalIterator pos,Args&&... args);

  template<typename T>
  iterator insert(T&& x);

  template<typename CollectionIterator,typename T>
  auto insert(CollectionIterator hint,T&& x);

  template<typename InputIterator>
  void insert(InputIterator first,InputIterator last);

  template<typename CollectionIterator,typename InputIterator>
  void insert(CollectionIterator hint,InputIterator first,InputIterator last);

  template<typename CollectionIterator>
  auto erase(CollectionIterator pos);

  template<typename CollectionIterator>
  auto erase(CollectionIterator first,CollectionIterator last);

  void clear()noexcept;
  void clear(const std::type_info& info);
  template<typename T> void clear();

  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 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 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) copy_n(first,args...)
(3) 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::copy_n(first,args...),
(3) std::rotate_copy(first,middle,last,args...).
Effects: Equivalent to expr.
Returns: expr.
Complexity: That of expr.

(1) alg<Ts...>(first,last,args...)
(2) copy_n<Ts...>(first,args...)
(3) 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::copy_n(rfirst,args...),
(3) 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... [21].
Effects: Equivalent to expr.
Returns: expr.
Complexity: That of expr.



[16] 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.

[17] The global end() iterator lies outside any segment, hence it always remain valid.

[18] Note that, unlike c.insert(i1,i2), these versions do not throw due to type registration problems.

[19] That is, the hint remains stable even if it may become invalid due to reallocations.

[20] The two previous notes apply here.

[21] 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.


PrevUpHomeNext