[DEV] add v1.66.0

This commit is contained in:
2018-01-12 21:47:58 +01:00
parent 87059bb1af
commit a97e9ae7d4
49032 changed files with 7668950 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
# Boost PolyCollection library
develop branch    [![Build Status](https://travis-ci.org/boostorg/poly_collection.svg?branch=develop)](https://travis-ci.org/boostorg/poly_collection) | master branch    [![Build Status](https://travis-ci.org/boostorg/poly_collection.svg?branch=master)](https://travis-ci.org/boostorg/poly_collection)
-|-
**Boost.PolyCollection**: fast containers of polymorphic objects.
[Online docs](http://boost.org/libs/poly_collection)
[Seminal article at bannalia.blogspot.com](http://bannalia.blogspot.com/2014/05/fast-polymorphic-collections.html)
Typically, polymorphic objects cannot be stored *directly* in regular containers
and need be accessed through an indirection pointer, which introduces performance
problems related to CPU caching and branch prediction. Boost.PolyCollection
implements a
[novel data structure](http://www.boost.org/doc/html/poly_collection/an_efficient_polymorphic_data_st.html)
that is able to contiguously store polymorphic objects without such indirection,
thus providing a value-semantics user interface and better performance.
Three *polymorphic collections* are provided:
* [`boost::base_collection`](http://www.boost.org/doc/html/poly_collection/tutorial.html#poly_collection.tutorial.basics.boost_base_collection)
* [`boost::function_collection`](http://www.boost.org/doc/html/poly_collection/tutorial.html#poly_collection.tutorial.basics.boost_function_collection)
* [`boost::any_collection`](http://www.boost.org/doc/html/poly_collection/tutorial.html#poly_collection.tutorial.basics.boost_any_collection)
dealing respectively with classic base/derived or OOP polymorphism, function wrapping
in the spirit of `std::function` and so-called
[*duck typing*](https://en.wikipedia.org/wiki/Duck_typing) as implemented by
[Boost.TypeErasure](http://www.boost.org/libs/type_erasure).
## Requirements
Boost.PolyCollection is a header-only library. C++11 support is required. The library has been verified to work with Visual Studio 2015, GCC 4.8 and Clang 3.3.

View File

@@ -0,0 +1,42 @@
# Copyright 2016-2017 Joaquín M López Muñoz.
# Copyright 2017 Rene Rivera
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org/libs/poly_collection for library home page.
using quickbook ;
using boostbook ;
# image dependencies
install images_standalone
: [ glob img/*.png ]
: <location>html/poly_collection/img
;
explicit images_standalone ;
install images_boostdoc
: [ glob img/*.png ]
: <location>../../../doc/html/poly_collection/img
;
explicit images_boostdoc ;
xml poly_collection : poly_collection.qbk ;
boostbook standalone
: poly_collection
:
<xsl:param>boost.defaults=Boost
<xsl:param>boost.image.src=poly_collection/img/boost.png
<xsl:param>boost.root=http://www.boost.org/doc/libs/develop
<dependency>images_standalone
;
alias boostdoc : poly_collection : : : <dependency>images_boostdoc ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,154 @@
[/
Copyright 2016-2017 Joaquin M Lopez Munoz.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
]
[template poly_collection_synopsis[class_name template_header value_type]
``[template_header]``
class ``[class_name]``
{
public:
``[link poly_collection.reference.polymorphic_containers.polymorphic_collections.types ['// types:]]``
using value_type=``[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 _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_;
``[link poly_collection.reference.polymorphic_containers.polymorphic_collections.construct_copy_destroy ['// construct/destroy/copy:]]``
``[class_name]``();
``[class_name]``(const ``[class_name]``&);
``[class_name]``(``[class_name]``&&);
explicit ``[class_name]``(const allocator_type& al);
``[class_name]``(const ``[class_name]``& x,const allocator_type& al);
``[class_name]``(``[class_name]``&& x,const allocator_type& al);
template<typename InputIterator>
``[link poly_collection.reference.polymorphic_containers.polymorphic_collections.construct_copy_destroy.range_construction [class_name]]``(
InputIterator first,InputIterator last,
const allocator_type& al=allocator_type{});
``[class_name]``& operator=(const ``[class_name]``&);
``[class_name]``& operator=(``[class_name]``&&);
allocator_type get_allocator()const noexcept;
``[link poly_collection.reference.polymorphic_containers.polymorphic_collections.type_registration ['// type registration:]]``
template<typename... T>
void _register_types_();
bool _is_registered_(const std::type_info& info)const;
template<typename T> bool _is_registered_()const;
``[link poly_collection.reference.polymorphic_containers.polymorphic_collections.iterators ['// 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;
``[link poly_collection.reference.polymorphic_containers.polymorphic_collections.capacity ['// 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_();
``[link poly_collection.reference.polymorphic_containers.polymorphic_collections.modifiers ['// 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_hint_(CollectionIterator hint,T&& x);
template<typename InputIterator>
void _insert_range_(InputIterator first,InputIterator last);
template<typename CollectionIterator,typename InputIterator>
void _insert_hint_range_(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(``[class_name]``& x);
};
]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,54 @@
/* Copyright 2003-2004 Joaqu<71>n M L<>pez Mu<4D>oz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
pre{
BORDER-RIGHT: gray 1pt solid;
PADDING-RIGHT: 2pt;
BORDER-TOP: gray 1pt solid;
DISPLAY: block;
PADDING-LEFT: 2pt;
PADDING-BOTTOM: 2pt;
BORDER-LEFT: gray 1pt solid;
MARGIN-RIGHT: 32pt;
PADDING-TOP: 2pt;
BORDER-BOTTOM: gray 1pt solid;
FONT-FAMILY: "Courier New", Courier, mono;
background-color: #EEEEEE;
}
table{
PADDING-RIGHT: 2pt;
BORDER-TOP: gray 1pt solid;
DISPLAY: block;
PADDING-LEFT: 2pt;
PADDING-BOTTOM: 2pt;
BORDER-LEFT: gray 1pt solid;
MARGIN-RIGHT: 32pt;
PADDING-TOP: 2pt;
background-color: #EEEEEE;
}
td{
BORDER-STYLE: solid;
BORDER-WIDTH: 1pt;
BORDER-LEFT: ;
BORDER-RIGHT: gray 1pt solid;
BORDER-TOP: ;
BORDER-BOTTOM: gray 1pt solid;
}
th{color: #ffffff; background-color: #000000;}
.odd_tr{background-color: #ffffff;}
.keyword{color: #0000FF;}
.identifier{}
.comment{font-style: italic; color: #008000;}
.special{color: #800040;}
.preprocessor{color: #3F007F;}
.string{font-style: italic; color: #666666;}
.literal{font-style: italic; color: #666666;}
.prev_link{width: 30%; float: left; text-align: left;}
.up_link{width: 39.9%; float: left; text-align: center;}
.next_link{width: 30%; float: left; text-align: right;}

View File

@@ -0,0 +1,49 @@
# Copyright 2016-2017 Joaqu<71>n M L<>pez Mu<4D>oz.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org/libs/poly_collection for library home page.
project
: requirements
<include>$(BOOST_ROOT)
<cxxstd>11
;
exe algorithms
: algorithms.cpp
: <cxxstd>14
;
exe basic_any
: basic_any.cpp
;
exe basic_base
: basic_base.cpp
;
exe basic_function
: basic_function.cpp
: <cxxstd>14
;
exe exceptions
: exceptions.cpp
;
exe insertion_emplacement
: insertion_emplacement.cpp
;
exe perf
: perf.cpp
:
: release
;
exe segmented_structure
: segmented_structure.cpp
: <cxxstd>14
;

View File

@@ -0,0 +1,171 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
/* Boost.PolyCollection algorithms */
#include <algorithm>
#include <boost/poly_collection/algorithm.hpp>
#include <boost/poly_collection/any_collection.hpp>
#include <boost/poly_collection/base_collection.hpp>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/typeid_of.hpp>
#include <random>
#include "rolegame.hpp"
std::ostream& operator<<(std::ostream& os,const sprite& s)
{
s.render(os);
return os;
}
std::ostream& operator<<(std::ostream& os,const window& w)
{
w.display(os);
return os;
}
int main()
{
boost::base_collection<sprite> c;
// populate c
std::mt19937 gen{92748}; // some arbitrary random seed
std::discrete_distribution<> rnd{{1,1,1}};
for(int i=0;i<8;++i){ // assign each type with 1/3 probability
switch(rnd(gen)){
case 0: c.insert(warrior{i});break;
case 1: c.insert(juggernaut{i});break;
case 2: c.insert(goblin{i});break;
}
}
auto render1=[](const boost::base_collection<sprite>& c){
//[algorithms_1
const char* comma="";
std::for_each(c.begin(),c.end(),[&](const sprite& s){
std::cout<<comma;
s.render(std::cout);
comma=",";
});
std::cout<<"\n";
//]
};
render1(c);
auto render2=[](const boost::base_collection<sprite>& c){
//[algorithms_2
const char* comma="";
for(auto seg_info:c.segment_traversal()){
for(const sprite& s:seg_info){
std::cout<<comma;
s.render(std::cout);
comma=",";
}
}
std::cout<<"\n";
//]
};
render2(c);
auto render3=[](const boost::base_collection<sprite>& c){
//[algorithms_3
//= #include <boost/poly_collection/algorithm.hpp>
//= ...
//=
const char* comma="";
boost::poly_collection::for_each(c.begin(),c.end(),[&](const sprite& s){
std::cout<<comma;
s.render(std::cout);
comma=",";
});
std::cout<<"\n";
//]
};
render3(c);
//[algorithms_4
auto n=boost::poly_collection::count_if(
c.begin(),c.end(),[](const sprite& s){return s.id%2==0;});
std::cout<<n<<" sprites with even id\n";
//]
using renderable=boost::type_erasure::ostreamable<>;
using standalone_renderable=boost::mpl::vector<
renderable,
boost::type_erasure::copy_constructible<>,
boost::type_erasure::typeid_<>
>;
{
//[algorithms_5
sprite* ps=new warrior{5};
// sprite -> warrior
warrior* pw=static_cast<warrior*>(ps);
//<-
(void)pw;
delete ps;
//->
//<-
boost::type_erasure::any<standalone_renderable> r=std::string{"hello"};
//->
//= boost::type_erasure::any<renderable> r=std::string{"hello"};
// renderable -> std::string
std::string& str=boost::type_erasure::any_cast<std::string&>(r);
//]
//[algorithms_6
// render r with std::string restitution
if(boost::type_erasure::typeid_of(r)==typeid(std::string)){
std::string& str=boost::type_erasure::any_cast<std::string&>(r);
std::cout<<str<<"\n";
}
else{
std::cout<<r<<"\n";
}
//]
}
auto& bc=c;
{
boost::any_collection<renderable> c;
c.insert(bc.begin<warrior>(),bc.end<warrior>());
c.insert(bc.begin<juggernaut>(),bc.end<juggernaut>());
c.insert(bc.begin<goblin>(),bc.end<goblin>());
c.insert(std::string{"\"stamina: 10,000\""});
c.insert(std::string{"\"game over\""});
c.insert(window{"pop-up 1"});
c.insert(window{"pop-up 2"});
//[algorithms_7
const char* comma="";
boost::poly_collection::for_each
<warrior,juggernaut,goblin>( // restituted types
c.begin(),c.end(),[&](const auto& x){ // loop traverses *all* elements
std::cout<<comma<<x;
comma=",";
});
std::cout<<"\n";
//]
}
//[algorithms_8
const char* comma="";
boost::poly_collection::for_each<warrior,juggernaut,goblin>(
c.begin(),c.end(),[&](const auto& s){
std::cout<<comma;
s.render(std::cout);
comma=",";
});
std::cout<<"\n";
//]
}

View File

@@ -0,0 +1,73 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
/* basic usage of boost::any_collection */
#include <boost/poly_collection/any_collection.hpp>
#include <boost/type_erasure/operators.hpp>
#include <random>
#include "rolegame.hpp"
//[basic_any_1
std::ostream& operator<<(std::ostream& os,const sprite& s)
{
s.render(os);
return os;
}
// std::string already has a suitable operator<<
std::ostream& operator<<(std::ostream& os,const window& w)
{
w.display(os);
return os;
}
//]
int main()
{
//[basic_any_2
//= #include <boost/poly_collection/any_collection.hpp>
//= #include <boost/type_erasure/operators.hpp>
//= ...
//=
using renderable=boost::type_erasure::ostreamable<>;
boost::any_collection<renderable> c;
//]
//[basic_any_3
// populate with sprites
std::mt19937 gen{92748}; // some arbitrary random seed
std::discrete_distribution<> rnd{{1,1,1}};
for(int i=0;i<4;++i){ // assign each type with 1/3 probability
switch(rnd(gen)){
case 0: c.insert(warrior{i});break;
case 1: c.insert(juggernaut{i});break;
case 2: c.insert(goblin{i});break;
}
}
// populate with messages
c.insert(std::string{"\"stamina: 10,000\""});
c.insert(std::string{"\"game over\""});
// populate with windows
c.insert(window{"pop-up 1"});
c.insert(window{"pop-up 2"});
//]
//[basic_any_4
const char* comma="";
for(const auto& r:c){
std::cout<<comma<<r;
comma=",";
}
std::cout<<"\n";
//]
}

View File

@@ -0,0 +1,59 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
/* basic usage of boost::base_collection */
#include <algorithm>
#include <boost/poly_collection/base_collection.hpp>
#include <random>
#include "rolegame.hpp"
int main()
{
//[basic_base_1
//= #include <boost/poly_collection/base_collection.hpp>
//= ...
//=
boost::base_collection<sprite> c;
std::mt19937 gen{92748}; // some arbitrary random seed
std::discrete_distribution<> rnd{{1,1,1}};
for(int i=0;i<8;++i){ // assign each type with 1/3 probability
switch(rnd(gen)){
case 0: c.insert(warrior{i});break;
case 1: c.insert(juggernaut{i});break;
case 2: c.insert(goblin{i});break;
}
}
//]
auto render=[&](){
//[basic_base_2
const char* comma="";
for(const sprite& s:c){
std::cout<<comma;
s.render(std::cout);
comma=",";
}
std::cout<<"\n";
//]
};
render();
//[basic_base_3
c.insert(goblin{8});
//]
render();
//[basic_base_4
// find element with id==7 and remove it
auto it=std::find_if(c.begin(),c.end(),[](const sprite& s){return s.id==7;});
c.erase(it);
//]
render();
}

View File

@@ -0,0 +1,103 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
/* basic usage of boost::function_collection */
#include <boost/poly_collection/function_collection.hpp>
#include <functional>
#include <memory>
#include <random>
#include <vector>
#include "rolegame.hpp"
int main()
{
//[basic_function_1
std::vector<std::unique_ptr<sprite>> sprs;
std::vector<std::string> msgs;
std::vector<window> wnds;
//]
// populate sprs
std::mt19937 gen{92748}; // some arbitrary random seed
std::discrete_distribution<> rnd{{1,1,1}};
for(int i=0;i<4;++i){ // assign each type with 1/3 probability
switch(rnd(gen)){
case 0: sprs.push_back(std::make_unique<warrior>(i));;break;
case 1: sprs.push_back(std::make_unique<juggernaut>(i));break;
case 2: sprs.push_back(std::make_unique<goblin>(i));break;
}
}
// populate msgs
msgs.push_back("\"stamina: 10,000\"");
msgs.push_back("\"game over\"");
// populate wnds
wnds.emplace_back("pop-up 1");
wnds.emplace_back("pop-up 2");
//[basic_function_2
//= #include <boost/poly_collection/function_collection.hpp>
//= ...
//=
// function signature accepting std::ostream& and returning nothing
using render_callback=void(std::ostream&);
boost::function_collection<render_callback> c;
//]
//[basic_function_3
//<-
auto render_sprite=[](const sprite& s){
//->
//= auto render_sprite(const sprite& s){
return [&](std::ostream& os){s.render(os);};
}/*<-*/;/*->*/
//<-
auto render_message=[](const std::string& m){
//->
//= auto render_message(const std::string& m){
return [&](std::ostream& os){os<<m;};
}/*<-*/;/*->*/
//<-
auto render_window=[](const window& w){
//->
//= auto render_window(const window& w){
return [&](std::ostream& os){w.display(os);};
}/*<-*/;/*->*/
//= ...
//=
for(const auto& ps:sprs)c.insert(render_sprite(*ps));
for(const auto& m:msgs)c.insert(render_message(m));
for(const auto& w:wnds)c.insert(render_window(w));
//]
//[basic_function_4
const char* comma="";
for(const auto& cbk:c){
std::cout<<comma;
cbk(std::cout);
comma=",";
}
std::cout<<"\n";
//]
//[basic_function_5
auto cbk=*c.begin();
cbk(std::cout); // renders first element to std::cout
std::function<render_callback> f=cbk;
f(std::cout); // exactly the same
//]
//[basic_function_6
//= *c.begin()=render_message("last minute message"); // compile-time error
//]
}

View File

@@ -0,0 +1,62 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
/* Boost.PolyCollection exceptions */
#include <algorithm>
#include <array>
#include <boost/poly_collection/base_collection.hpp>
#include <random>
#include "rolegame.hpp"
int main()
{
boost::base_collection<sprite> c,c2;
// populate c
std::mt19937 gen{92748}; // some arbitrary random seed
std::discrete_distribution<> rnd{{1,1,1}};
for(int i=0;i<8;++i){ // assign each type with 1/3 probability
switch(rnd(gen)){
case 0: c.insert(warrior{i});break;
case 1: c.insert(juggernaut{i});break;
case 2: c.insert(goblin{i});break;
}
}
auto render=[](const boost::base_collection<sprite>& c){
const char* comma="";
for(const sprite& s:c){
std::cout<<comma;
s.render(std::cout);
comma=",";
}
std::cout<<"\n";
};
render(c);
try{
//[exceptions_1
c.insert(elf{0}); // no problem
//= ...
//=
c2=c; // throws boost::poly_collection::not_copy_constructible
//]
}catch(boost::poly_collection::not_copy_constructible&){}
try{
//[exceptions_2
c.clear<elf>(); // get rid of non-copyable elfs
c2=c; // now it works
// check that the two are indeed equal
std::cout<<(c==c2)<<"\n";
// throws boost::poly_collection::not_equality_comparable
//]
}catch(boost::poly_collection::not_equality_comparable&){}
}

View File

@@ -0,0 +1,109 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
/* examples of insertion and emplacement */
#include <algorithm>
#include <array>
#include <boost/poly_collection/base_collection.hpp>
#include <random>
#include "rolegame.hpp"
int main()
{
boost::base_collection<sprite> c;
// populate c
std::mt19937 gen{92748}; // some arbitrary random seed
std::discrete_distribution<> rnd{{1,1,1}};
for(int i=0;i<8;++i){ // assign each type with 1/3 probability
switch(rnd(gen)){
case 0: c.insert(warrior{i});break;
case 1: c.insert(juggernaut{i});break;
case 2: c.insert(goblin{i});break;
}
}
auto render=[](const boost::base_collection<sprite>& c){
const char* comma="";
for(const sprite& s:c){
std::cout<<comma;
s.render(std::cout);
comma=",";
}
std::cout<<"\n";
};
render(c);
//[insertion_emplacement_1]
c.insert(c.begin(),juggernaut{8});
//]
render(c);
//[insertion_emplacement_2]
c.insert(c.begin(),goblin{9});
//]
render(c);
//[insertion_emplacement_3]
c.insert(c.begin<juggernaut>()+2,juggernaut{10});
// ^^ remember local iterators are random access
//]
render(c);
//[insertion_emplacement_4]
//= c.insert(c.begin(typeid(warrior)),juggernaut{11}); // undefined behavior!!
//]
//[insertion_emplacement_5]
boost::base_collection<sprite> c2;
c2.insert(c.begin(),c.end()); // read below
//<-
render(c2);
//->
// add some more warriors
std::array<warrior,3> aw={{11,12,13}};
c2.insert(aw.begin(),aw.end());
//<-
render(c2);
//->
// add some goblins at the beginning of their segment
std::array<goblin,3> ag={{14,15,16}};
c2.insert(c2.begin<goblin>(),ag.begin(),ag.end());
//<-
render(c2);
//->
//]
//[insertion_emplacement_6]
//<-
// same as line at beginning of previous snippet
//->
c2.insert(c.begin(),c.end());
//]
//[insertion_emplacement_7]
//= c.emplace(11); // does not compile
//]
//[insertion_emplacement_8]
c.emplace<goblin>(11); // now it works
//]
render(c);
//[insertion_emplacement_9]
c.emplace_hint<juggernaut>(c.begin(),12); // at the beginning if possible
c.emplace_pos<goblin>(c.begin<goblin>()+2,13); // amidst the goblins
c.emplace_pos<warrior>(c.begin(typeid(warrior)),14); // local_base_iterator
//]
render(c);
}

View File

@@ -0,0 +1,604 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
/* Boost.PolyCollection performance tests */
#include <algorithm>
#include <array>
#include <chrono>
#include <cmath>
#include <numeric>
std::chrono::high_resolution_clock::time_point measure_start,measure_pause;
template<typename F>
double measure(F f)
{
using namespace std::chrono;
static const int num_trials=10;
static const milliseconds min_time_per_trial(200);
std::array<double,num_trials> trials;
volatile decltype(f()) res; /* to avoid optimizing f() away */
for(int i=0;i<num_trials;++i){
int runs=0;
high_resolution_clock::time_point t2;
measure_start=high_resolution_clock::now();
do{
res=f();
++runs;
t2=high_resolution_clock::now();
}while(t2-measure_start<min_time_per_trial);
trials[i]=duration_cast<duration<double>>(t2-measure_start).count()/runs;
}
(void)res; /* var not used warn */
std::sort(trials.begin(),trials.end());
return std::accumulate(
trials.begin()+2,trials.end()-2,0.0)/(trials.size()-4);
}
template<typename F>
double measure(unsigned int n,F f)
{
double t=measure(f);
return (t/n)*10E9;
}
void pause_timing()
{
measure_pause=std::chrono::high_resolution_clock::now();
}
void resume_timing()
{
measure_start+=std::chrono::high_resolution_clock::now()-measure_pause;
}
#include <algorithm>
#include <array>
#include <boost/poly_collection/algorithm.hpp>
#include <boost/poly_collection/any_collection.hpp>
#include <boost/poly_collection/base_collection.hpp>
#include <boost/poly_collection/function_collection.hpp>
#include <boost/ptr_container/ptr_container.hpp>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/callable.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/typeid_of.hpp>
#include <functional>
#include <random>
#include <string>
#include <utility>
#include <vector>
//[perf_base_types
struct base
{
virtual ~base()=default;
virtual int operator()(int)const=0;
};
struct derived1 final:base
{
derived1(int n):n{n}{}
virtual int operator()(int)const{return n;}
int n;
};
struct derived2 final:base
{
derived2(int n):n{n}{}
virtual int operator()(int x)const{return x*n;}
int unused,n;
};
struct derived3 final:base
{
derived3(int n):n{n}{}
virtual int operator()(int x)const{return x*x*n;}
int unused,n;
};
//]
//[perf_function_types
struct concrete1
{
concrete1(int n):n{n}{}
int operator()(int)const{return n;}
int n;
};
struct concrete2
{
concrete2(int n):n{n}{}
int operator()(int x)const{return x*n;}
int unused,n;
};
struct concrete3
{
concrete3(int n):n{n}{}
int operator()(int x)const{return x*x*n;}
int unused,n;
};
//]
template<typename Base>
struct ptr_vector:boost::ptr_vector<Base>
{
public:
template<typename T>
void insert(const T& x)
{
this->push_back(new T{x});
}
template<typename F>
void for_each(F f)
{
std::for_each(this->begin(),this->end(),f);
}
void prepare_for_for_each(){}
};
template<typename Base>
struct sorted_ptr_vector:ptr_vector<Base>
{
void prepare_for_for_each()
{
std::sort(
this->c_array(),this->c_array()+this->size(),
[](Base* x,Base* y){return typeid(*x).before(typeid(*y));});
}
};
template<typename Base>
struct shuffled_ptr_vector:ptr_vector<Base>
{
void prepare_for_for_each()
{
std::shuffle(
this->c_array(),this->c_array()+this->size(),std::mt19937(1));
}
};
template<typename Base>
struct base_collection:boost::base_collection<Base>
{
template<typename F>
void for_each(F f)
{
std::for_each(this->begin(),this->end(),f);
}
void prepare_for_for_each(){}
};
template<typename Base,typename... T>
struct poly_for_each_base_collection:base_collection<Base>
{
template<typename F>
void for_each(F f)
{
boost::poly_collection::for_each<T...>(this->begin(),this->end(),f);
}
};
template<typename Signature>
struct func_vector:std::vector<std::function<Signature>>
{
template<typename T> void insert(const T& x)
{
this->push_back(x);
}
template<typename F>
void for_each(F f)
{
std::for_each(this->begin(),this->end(),f);
}
void prepare_for_for_each(){}
};
template<typename Signature>
struct sorted_func_vector:func_vector<Signature>
{
void prepare_for_for_each()
{
using value_type=typename sorted_func_vector::value_type;
std::sort(
this->begin(),this->end(),[](const value_type& x,const value_type& y){
return x.target_type().before(y.target_type());
});
}
};
template<typename Signature>
struct shuffled_func_vector:func_vector<Signature>
{
void prepare_for_for_each()
{
std::shuffle(this->begin(),this->end(),std::mt19937(1));
}
};
template<typename Signature>
struct func_collection:boost::function_collection<Signature>
{
template<typename F>
void for_each(F f)
{
std::for_each(this->begin(),this->end(),f);
}
void prepare_for_for_each(){}
};
template<typename Signature,typename... T>
struct poly_for_each_func_collection:func_collection<Signature>
{
template<typename F>
void for_each(F f)
{
boost::poly_collection::for_each<T...>(this->begin(),this->end(),f);
}
};
template<typename Concept>
struct any_vector:std::vector<boost::type_erasure::any<Concept>>
{
template<typename T> void insert(const T& x)
{
this->push_back(x);
}
template<typename F>
void for_each(F f)
{
std::for_each(this->begin(),this->end(),f);
}
void prepare_for_for_each(){}
};
template<typename Concept>
struct sorted_any_vector:any_vector<Concept>
{
void prepare_for_for_each()
{
using value_type=typename sorted_any_vector::value_type;
std::sort(
this->begin(),this->end(),[](const value_type& x,const value_type& y){
return typeid_of(x).before(typeid_of(y));
});
}
};
template<typename Concept>
struct shuffled_any_vector:any_vector<Concept>
{
void prepare_for_for_each()
{
std::shuffle(this->begin(),this->end(),std::mt19937(1));
}
};
template<typename Concept>
struct any_collection:boost::any_collection<Concept>
{
template<typename F>
void for_each(F f)
{
std::for_each(this->begin(),this->end(),f);
}
void prepare_for_for_each(){}
};
template<typename Concept,typename... T>
struct poly_for_each_any_collection:any_collection<Concept>
{
template<typename F>
void for_each(F f)
{
boost::poly_collection::for_each<T...>(this->begin(),this->end(),f);
}
};
#include <iostream>
template<typename... Printables>
void print(Printables... ps)
{
const char* delim="";
using seq=int[1+sizeof...(ps)];
(void)seq{0,(std::cout<<delim<<ps,delim=";",0)...};
std::cout<<"\n";
}
template<typename T>
struct label
{
label(const char* str):str{str}{}
operator const char*()const{return str;}
const char* str;
};
template<typename... T>
struct element_sequence{};
template<
typename... Element,
typename Container
>
void container_fill(unsigned int n,element_sequence<Element...>,Container& c)
{
auto m=n/sizeof...(Element);
for(unsigned int i=0;i!=m;++i){
using seq=int[sizeof...(Element)];
(void)seq{(c.insert(Element(i)),0)...};
}
}
struct insert_perf_functor
{
template<
typename... Element,
typename Container
>
std::size_t operator()(
unsigned int n,element_sequence<Element...> elements,label<Container>)const
{
pause_timing();
std::size_t res=0;
{
Container c;
resume_timing();
container_fill(n,elements,c);
pause_timing();
res=c.size();
}
resume_timing();
return res;
}
};
template<
typename... Element,
typename Container
>
double insert_perf(
unsigned int n,element_sequence<Element...> elements,label<Container> label)
{
return measure(n,std::bind(insert_perf_functor{},n,elements,label));
}
template<
typename... Element,
typename... Container
>
void insert_perf(
unsigned int n0,unsigned int n1,unsigned int dsav,
element_sequence<Element...> elements,label<Container>... labels)
{
std::cout<<"insert:\n";
print("n",labels...);
for(unsigned int s=0,n=n0;
(n=(unsigned int)std::round(n0*std::pow(10.0,s/1000.0)))<=n1;
s+=dsav){
unsigned int m=(unsigned int)std::round(n/sizeof...(Element)),
nn=m*sizeof...(Element);
print(nn,insert_perf(nn,elements,labels)...);
}
}
struct for_each_perf_functor
{
template<typename F,typename Container>
auto operator()(F f,Container& c)const->decltype(f.res)
{
c.for_each(std::ref(f));
return f.res;
}
};
template<
typename... Element,
typename F,
typename Container
>
double for_each_perf(
unsigned int n,
element_sequence<Element...> elements,F f,label<Container>)
{
Container c;
container_fill(n,elements,c);
c.prepare_for_for_each();
return measure(n,std::bind(for_each_perf_functor{},f,std::ref(c)));
}
template<
typename... Element,
typename F,
typename... Container
>
void for_each_perf(
unsigned int n0,unsigned int n1,unsigned int dsav,
element_sequence<Element...> elements,F f,label<Container>... labels)
{
std::cout<<"for_each:\n";
print("n",labels...);
for(unsigned int s=0,n=n0;
(n=(unsigned int)std::round(n0*std::pow(10.0,s/1000.0)))<=n1;
s+=dsav){
unsigned int m=(unsigned int)std::round(n/sizeof...(Element)),
nn=m*sizeof...(Element);
print(nn,for_each_perf(nn,elements,f,labels)...);
}
}
//[perf_for_each_callable
struct for_each_callable
{
for_each_callable():res{0}{}
template<typename T>
void operator()(T& x){
res+=x(2);
}
int res;
};
//]
//[perf_for_each_incrementable
struct for_each_incrementable
{
for_each_incrementable():res{0}{}
template<typename T>
void operator()(T& x){
++x;
++res;
}
int res;
};
//]
int main(int argc, char *argv[])
{
using test=std::pair<std::string,bool&>;
bool all=false,
insert_base=false,
for_each_base=false,
insert_function=false,
for_each_function=false,
insert_any=false,
for_each_any=false;
std::array<test,7> tests={{
{"all",all},
{"insert_base",insert_base},
{"for_each_base",for_each_base},
{"insert_function",insert_function},
{"for_each_function",for_each_function},
{"insert_any",insert_any},
{"for_each_any",for_each_any}
}};
if(argc<2){
std::cout<<"specify one or more tests to execute:\n";
for(const auto& p:tests)std::cout<<" "<<p.first<<"\n";
return 1;
}
for(int arg=1;arg<argc;++arg){
auto it=std::find_if(tests.begin(),tests.end(),[&](test& t){
return t.first==argv[arg];
});
if(it==tests.end()){
std::cout<<"invalid test name\n";
return 1;
}
it->second=true;
}
unsigned int n0=100,n1=10000000,dsav=50; /* sav for savart */
{
auto seq= element_sequence<
derived1,derived1,derived2,derived2,derived3>{};
auto f= for_each_callable{};
auto pv= label<ptr_vector<base>>
{"ptr_vector"};
auto spv= label<sorted_ptr_vector<base>>
{"sorted ptr_vector"};
auto shpv= label<shuffled_ptr_vector<base>>
{"shuffled ptr_vector"};
auto bc= label<base_collection<base>>
{"base_collection"};
auto fbc= label<poly_for_each_base_collection<base>>
{"base_collection (poly::for_each)"};
auto rfbc= label<
poly_for_each_base_collection<base,derived1,derived2,derived2>
>
{"base_collection (restituted poly::for_each)"};
if(all||insert_base)insert_perf(n0,n1,dsav,seq,pv,bc);
if(all||for_each_base)for_each_perf(
n0,n1,dsav,seq,f,pv,spv,shpv,bc,fbc,rfbc);
}
{
using signature=int(int);
auto seq= element_sequence<
concrete1,concrete1,concrete2,concrete2,concrete3>{};
auto f = for_each_callable{};
auto fv= label<func_vector<signature>>
{"func_vector"};
auto sfv= label<sorted_func_vector<signature>>
{"sorted func_vector"};
auto shfv= label<shuffled_func_vector<signature>>
{"shuffled func_vector"};
auto fc= label<func_collection<signature>>
{"function_collection"};
auto ffc= label<poly_for_each_func_collection<signature>>
{"function_collection (poly::for_each)"};
auto rffc= label<poly_for_each_func_collection<
signature,concrete1,concrete2,concrete3>>
{"function_collection (restituted poly::for_each)"};
if(all||insert_function)insert_perf(n0,n1,dsav,seq,fv,fc);
if(all||for_each_function)for_each_perf(
n0,n1,dsav,seq,f,fv,sfv,shfv,fc,ffc,rffc);
}
{
//[perf_any_types
using concept_=boost::mpl::vector<
boost::type_erasure::copy_constructible<>,
boost::type_erasure::relaxed,
boost::type_erasure::typeid_<>,
boost::type_erasure::incrementable<>
>;
//]
auto seq= element_sequence<int,int,double,double,char>{};
auto f= for_each_incrementable{};
auto av= label<any_vector<concept_>>
{"any_vector"};
auto sav= label<sorted_any_vector<concept_>>
{"sorted any_vector"};
auto shav= label<shuffled_any_vector<concept_>>
{"shuffled any_vector"};
auto ac= label<any_collection<concept_>>
{"any_collection"};
auto fac= label<poly_for_each_any_collection<concept_>>
{"any_collection (poly::for_each)"};
auto rfac= label<poly_for_each_any_collection<concept_,int,double,char>>
{"any_collection (restituted poly::for_each)"};
if(all||insert_any)insert_perf(n0,n1,dsav,seq,av,ac);
if(all||for_each_any)for_each_perf(
n0,n1,dsav,seq,f,av,sav,shav,ac,fac,rfac);
}
}

View File

@@ -0,0 +1,78 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#ifndef BOOST_POLY_COLLECTION_EXAMPLE_ROLEGAME_HPP
#define BOOST_POLY_COLLECTION_EXAMPLE_ROLEGAME_HPP
#if defined(_MSC_VER)
#pragma once
#endif
/* entities of a purported role game used in the examples */
#include <iostream>
#include <string>
#include <utility>
//[rolegame_1
struct sprite
{
sprite(int id):id{id}{}
virtual ~sprite()=default;
virtual void render(std::ostream& os)const=0;
int id;
};
//]
//[rolegame_2
struct warrior:sprite
{
using sprite::sprite;
warrior(std::string rank,int id):sprite{id},rank{std::move(rank)}{}
void render(std::ostream& os)const override{os<<rank<<" "<<id;}
std::string rank="warrior";
};
struct juggernaut:warrior
{
juggernaut(int id):warrior{"juggernaut",id}{}
};
struct goblin:sprite
{
using sprite::sprite;
void render(std::ostream& os)const override{os<<"goblin "<<id;}
};
//]
//[rolegame_3
struct window
{
window(std::string caption):caption{std::move(caption)}{}
void display(std::ostream& os)const{os<<"["<<caption<<"]";}
std::string caption;
};
//]
//[rolegame_4
struct elf:sprite
{
using sprite::sprite;
elf(const elf&)=delete; // not copyable
elf(elf&&)=default; // but moveable
void render(std::ostream& os)const override{os<<"elf "<<id;}
};
//]
#endif

View File

@@ -0,0 +1,181 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
/* segment-specific operations */
#include <algorithm>
#include <boost/poly_collection/any_collection.hpp>
#include <boost/poly_collection/base_collection.hpp>
#include <boost/type_erasure/operators.hpp>
#include <memory>
#include <random>
#include "rolegame.hpp"
std::ostream& operator<<(std::ostream& os,const sprite& s)
{
s.render(os);
return os;
}
std::ostream& operator<<(std::ostream& os,const window& w)
{
w.display(os);
return os;
}
int main()
{
boost::base_collection<sprite> c;
//[segmented_structure_1
//= std::unique_ptr<sprite> make_sprite()
//= {
//<-
auto make_sprite=[]()->std::unique_ptr<sprite>{
//->
static std::mt19937 gen{92748};
static std::discrete_distribution<> rnd{{1,1,1}};
static int id=0;
switch(rnd(gen)){
//<-
default:
//->
case 0: return std::make_unique<warrior>(id++);break;
case 1: return std::make_unique<juggernaut>(id++);break;
case 2: return std::make_unique<goblin>(id++);break;
}
//<-
};
//->
//= }
//= ...
//=
//<-
try{
//->
for(int i=0;i<8;++i)c.insert(*make_sprite());
// throws boost::poly_collection::unregistered_type
//<-
}catch(boost::poly_collection::unregistered_type&){}
//->
//]
//[segmented_structure_2
std::cout<<c.is_registered<warrior>()<<"\n"; // prints 0
std::cout<<c.is_registered(typeid(warrior))<<"\n"; // alternate syntax
//]
//[segmented_structure_3
c.register_types<warrior,juggernaut,goblin>();
// everything works fine now
for(int i=0;i<8;++i)c.insert(*make_sprite());
//]
using renderable=boost::type_erasure::ostreamable<>;
//[segmented_structure_4
boost::any_collection<renderable> c1,c2;
//= ... // populate c2
//=
//<-
c2.insert(window{"pop-up"});
try{
//->
c1.insert(*c2.begin()); // throws: actual type of *c2.begin() not known by c1
//<-
}catch(boost::poly_collection::unregistered_type&){}
//->
//]
//[segmented_structure_5
//= ... // populate c with 8 assorted entities
//=
std::cout<<c.size()<<"\n"; // 8 sprites
std::cout<<c.size<juggernaut>()<<"\n"; // 2 juggernauts
std::cout<<c.size(typeid(juggernaut))<<"\n"; // alternate syntax
c.clear<juggernaut>(); // remove juggenauts only
std::cout<<c.empty<juggernaut>()<<"\n"; // 1 (no juggernauts left)
std::cout<<c.size()<<"\n"; // 6 sprites remaining
//]
//[segmented_structure_6
const char* comma="";
for(auto first=c.begin(typeid(warrior)),last=c.end(typeid(warrior));
first!=last;++first){
std::cout<<comma;
first->render(std::cout);
comma=",";
}
std::cout<<"\n";
//]
//[segmented_structure_7
/*=const char**/ comma="";
for(const auto& x:c.segment(typeid(warrior))){
std::cout<<comma;
x.render(std::cout);
comma=",";
}
std::cout<<"\n";
//]
//[segmented_structure_8
/*=const char**/ comma="";
for(auto first=c.begin<warrior>(),last=c.end<warrior>();
first!=last;++first){
first->rank.insert(0,"super");
std::cout<<comma;
first->render(std::cout);
comma=",";
}
std::cout<<"\n";
// range-based for loop alternative
/*=const char**/ comma="";
for(auto& x:c.segment<warrior>()){
x.rank.insert(0,"super");
//<-
auto it=x.rank.begin();
x.rank.erase(it,it+5); // undo previos op, 5==len("super");
//->
std::cout<<comma;
x.render(std::cout);
comma=",";
}
std::cout<<"\n";
//]
auto render=[&](){
//[segmented_structure_9
const char* comma="";
for(auto seg:c.segment_traversal()){
for(sprite& s:seg){
std::cout<<comma;
s.render(std::cout);
comma=",";
}
}
std::cout<<"\n";
//]
};
render();
//[segmented_structure_10
c.reserve<goblin>(100); // no reallocation till we exceed 100 goblins
std::cout<<c.capacity<goblin>()<<"\n"; // prints 100
//]
//[segmented_structure_11
c.reserve(1000); // reserve(1000) for each segment
std::cout<<c.capacity<warrior>()<<", "
<<c.capacity<juggernaut>()<<", "
<<c.capacity<goblin>()<<"\n"; // prints 1000, 1000, 1000
//]
}

View File

@@ -0,0 +1,20 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
<!--
Copyright 2016-2017 Joaquín M López Muñoz.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="refresh" content="0; URL=../../doc/html/poly_collection.html">
<title>Boost.PolyCollection Documentation</title>
<link rel="stylesheet" href="doc/style.css" type="text/css">
</head>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/poly_collection.html">../../doc/html/poly_collection.html</a>
</body>
</html>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 Joaquin M Lopez Munoz.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
See http://www.boost.org/libs/poly_collection for library home page.
-->
<explicit-failures-markup>
<library name="poly_collection">
<mark-unusable>
<toolset name="clang*-3.0*"/>
<toolset name="clang*-3.1*"/>
<toolset name="clang*-3.2*"/>
<toolset name="gcc*-3.*"/>
<toolset name="gcc*-4.0*"/>
<toolset name="gcc*-4.1*"/>
<toolset name="gcc*-4.2*"/>
<toolset name="gcc*-4.3*"/>
<toolset name="gcc*-4.4*"/>
<toolset name="gcc*-4.5*"/>
<toolset name="gcc*-4.6*"/>
<toolset name="gcc*-4.7*"/>
<toolset name="qcc*-3.*"/>
<toolset name="qcc*-4.0*"/>
<toolset name="qcc*-4.1*"/>
<toolset name="qcc*-4.2*"/>
<toolset name="qcc*-4.3*"/>
<toolset name="qcc*-4.4*"/>
<toolset name="qcc*-4.5*"/>
<toolset name="qcc*-4.6*"/>
<toolset name="qcc*-4.7*"/>
<toolset name="msvc-7.1"/>
<toolset name="msvc-8.0"/>
<toolset name="msvc-9.0"/>
<toolset name="msvc-10.0"/>
<toolset name="msvc-11.0"/>
<toolset name="msvc-12.0"/>
<note author="Joaqu&#237;n M L&#243;pez Mu&#241;oz" date="18 Jun 2017">
Compiler's too old for working.
</note>
</mark-unusable>
<mark-unusable>
<toolset name="*98"/>
<note author="Joaqu&#237;n M L&#243;pez Mu&#241;oz" date="18 Jun 2017">
C++11 or later required.
</note>
</mark-unusable>
</library>
</explicit-failures-markup>

View File

@@ -0,0 +1,14 @@
{
"key": "poly_collection",
"name": "PolyCollection",
"authors": [
"Joaqu\u00edn M L\u00f3pez Mu\u00f1oz"
],
"description": "Fast containers of polymorphic objects.",
"category": [
"Containers"
],
"maintainers": [
"Joaquin M Lopez Munoz <joaquin.lopezmunoz -at- gmail.com>"
]
}

View File

@@ -0,0 +1,43 @@
# Copyright 2016-2017 Joaqu<71>n M L<>pez Mu<4D>oz.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org/libs/poly_collection for library home page.
import testing ;
import ../../config/checks/config : requires ;
project
: requirements
[ requires cxx11_noexcept ] # used as a proxy for C++11 support
<toolset>msvc:<cxxflags>-D_SCL_SECURE_NO_WARNINGS
;
test-suite "poly_collection" :
[ run test_algorithm.cpp test_algorithm1.cpp
test_algorithm2.cpp test_algorithm3.cpp
test_algorithm_main.cpp
:
:
: <toolset>msvc:<cxxflags>/bigobj
<toolset>gcc:<inlining>on
<toolset>gcc:<optimization>space
<toolset>clang:<inlining>on
<toolset>clang:<optimization>space ]
[ run test_capacity.cpp test_capacity_main.cpp ]
[ run test_comparison.cpp test_comparison_main.cpp ]
[ run test_construction.cpp test_construction_main.cpp
:
:
: <toolset>msvc:<cxxflags>/bigobj
<toolset>gcc:<inlining>on
<toolset>gcc:<optimization>space
<toolset>clang:<inlining>on
<toolset>clang:<optimization>space ]
[ run test_emplacement.cpp test_emplacement_main.cpp ]
[ run test_erasure.cpp test_erasure_main.cpp ]
[ run test_insertion.cpp test_insertion_main.cpp ]
[ run test_iterators.cpp test_iterators_main.cpp ]
[ run test_registration.cpp test_registration_main.cpp ]
;

View File

@@ -0,0 +1,96 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#ifndef BOOST_POLY_COLLECTION_TEST_ANY_TYPES_HPP
#define BOOST_POLY_COLLECTION_TEST_ANY_TYPES_HPP
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/mpl/vector/vector10.hpp>
#include <boost/poly_collection/any_collection.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/call.hpp>
#include <boost/type_erasure/operators.hpp>
namespace any_types{
struct incrementable1
{
incrementable1(int n):n{n}{}
incrementable1(incrementable1&&)=default;
incrementable1(const incrementable1&)=delete;
incrementable1& operator=(incrementable1&&)=default;
incrementable1& operator=(const incrementable1&)=delete;
bool operator==(const incrementable1& x)const{return n==x.n;}
incrementable1& operator++(){++n;return *this;}
int n;
};
struct incrementable3
{
incrementable3():n{-1}{}
incrementable3(int n):n{(double)n}{}
incrementable3& operator++(){++n;return *this;}
double n;
};
using concept_=boost::type_erasure::incrementable<>;
using collection=boost::any_collection<concept_>;
template<typename T=boost::type_erasure::_self>
struct convertible_to_int
{
static int apply(const T& x){return x;}
};
using t1=incrementable1;
using t2=double;
using t3=incrementable3;
using t4=int;
using t5=boost::type_erasure::any<
boost::mpl::vector4<
boost::type_erasure::copy_constructible<>,
boost::type_erasure::assignable<>,
concept_,
convertible_to_int<>
>
>;
struct to_int
{
to_int(){};
template<typename Concept,typename Tag>
int operator()(const boost::type_erasure::any<Concept,Tag>& x)const
{
using boost::type_erasure::any_cast;
if(auto p=any_cast<t1*>(&x))return (*this)(*p);
if(auto p=any_cast<t2*>(&x))return (*this)(*p);
if(auto p=any_cast<t3*>(&x))return (*this)(*p);
if(auto p=any_cast<t4*>(&x))return (*this)(*p);
if(auto p=any_cast<t5*>(&x))return (*this)(*p);
else return 0;
}
int operator()(const t1& x)const{return x.n;}
int operator()(const t2& x)const{return static_cast<int>(x);};
int operator()(const t3& x)const{return static_cast<int>(x.n);}
int operator()(const t4& x)const{return x;}
int operator()(const t5& x)const
{
return boost::type_erasure::call(convertible_to_int<>{},x);
}
};
} /* namespace any_types */
#endif

View File

@@ -0,0 +1,94 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#ifndef BOOST_POLY_COLLECTION_TEST_BASE_TYPES_HPP
#define BOOST_POLY_COLLECTION_TEST_BASE_TYPES_HPP
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/poly_collection/base_collection.hpp>
namespace base_types{
struct base
{
virtual ~base()=default;
virtual int operator()(int)const=0;
};
struct derived1 final:base
{
derived1(int n):n{n}{}
derived1(derived1&&)=default;
derived1(const derived1&)=delete;
derived1& operator=(derived1&&)=default;
derived1& operator=(const derived1&)=delete;
virtual int operator()(int)const{return n;}
bool operator==(const derived1& x)const{return n==x.n;}
int n;
};
struct derived2:base
{
derived2(int n):n{n}{}
derived2(derived2&&)=default;
derived2& operator=(derived2&&)=delete;
virtual int operator()(int x)const{return x*n;}
bool operator==(const derived2& x)const{return n==x.n;}
int n;
};
struct derived3:base
{
derived3():n{-1}{}
derived3(int n):n{n}{}
virtual int operator()(int x)const{return x*x*n;}
int n;
};
struct another_base
{
virtual ~another_base()=default;
char x[5];
};
struct derived4:another_base,derived3
{
using derived3::derived3;
virtual int operator()(int x)const{return -(this->derived3::operator()(x));}
bool operator==(const derived4& x)const{return n==x.n;}
};
struct derived5:base,another_base
{
derived5(int n):n{n}{}
virtual int operator()(int x)const{return x*x*x*n;}
int n;
};
using collection=boost::base_collection<base>;
using t1=derived1;
using t2=derived2;
using t3=derived3;
using t4=derived4;
using t5=derived5;
struct to_int
{
to_int(){};
template<typename F>
int operator()(const F& f)const{return f(1);}
};
} /* namespace base_types */
#endif

View File

@@ -0,0 +1,146 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#ifndef BOOST_POLY_COLLECTION_TEST_FUNCTION_TYPES_HPP
#define BOOST_POLY_COLLECTION_TEST_FUNCTION_TYPES_HPP
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/poly_collection/function_collection.hpp>
#include <typeinfo>
namespace function_types{
struct function1 final
{
function1(int n):n{n}{}
function1(function1&&)=default;
function1(const function1&)=delete;
function1& operator=(function1&&)=default;
function1& operator=(const function1&)=delete;
int operator()(int)const{return n;}
friend bool operator==(
const function1& x,const function1& y){return x.n==y.n;}
int n;
};
struct function2
{
function2(int n):n{n}{}
int operator()(int x)const{return x*n;}
bool operator==(const function2& x)const{return n==x.n;}
int n;
};
struct function3
{
function3():n{-1}{}
function3(int n):n{n}{}
int operator()(int x)const{return x*x*n;}
int n;
};
struct function4:function3
{
using function3::function3;
int operator()(int x)const{return -(this->function3::operator()(x));}
bool operator==(const function4& x)const{return n==x.n;}
};
struct function5
{
function5(int n):n{n}{}
int operator()(int x)const{return x*x*x*n;}
int n;
};
struct int_alias /* brings this namespace into ADL for operator== below */
{
int_alias(int n):n{n}{}
operator int()const{return n;}
int n;
};
using signature=int_alias(int);
using collection=boost::function_collection<signature>;
using t1=function1;
using t2=function2;
using t3=function3;
using t4=function4;
using t5=function5;
inline bool operator==(
const collection::value_type& x,const collection::value_type& y)
{
const std::type_info& xi=x.target_type();
const std::type_info& yi=y.target_type();
if(xi==yi){
if(xi==typeid(t1))return (*x.target<t1>())==(*y.target<t1>());
if(xi==typeid(t2))return (*x.target<t2>()).operator==(*y.target<t2>());
if(xi==typeid(t4))return (*x.target<t4>()).operator==(*y.target<t4>());
}
return false;
}
inline bool operator==(const collection::value_type& x,const t1& y)
{
const std::type_info& xi=x.target_type();
if(xi==typeid(t1))return (*x.target<t1>())==y;
return false;
}
inline bool operator==(const t1& x,const collection::value_type& y)
{
return y==x;
}
inline bool operator==(const collection::value_type& x,const t2& y)
{
const std::type_info& xi=x.target_type();
if(xi==typeid(t2))return (*x.target<t2>())==y;
return false;
}
inline bool operator==(const t2& x,const collection::value_type& y)
{
return y==x;
}
inline bool operator==(const collection::value_type& x,const t4& y)
{
const std::type_info& xi=x.target_type();
if(xi==typeid(t4))return (*x.target<t4>())==y;
return false;
}
inline bool operator==(const t4& x,const collection::value_type& y)
{
return y==x;
}
inline bool operator==(const t1&,const t2&){return false;}
inline bool operator==(const t1&,const t4&){return false;}
inline bool operator==(const t2&,const t1&){return false;}
inline bool operator==(const t2&,const t4&){return false;}
inline bool operator==(const t4&,const t1&){return false;}
inline bool operator==(const t4&,const t2&){return false;}
struct to_int
{
to_int(){};
template<typename F>
int operator()(const F& f)const{return f(1);}
};
} /* namespace function_types */
#endif

View File

@@ -0,0 +1,21 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_algorithm.hpp"
#include "test_algorithm1.hpp"
#include "test_algorithm2.hpp"
#include "test_algorithm3.hpp"
/* test split in chunks to avoid problems with compilation object sizes */
void test_algorithm()
{
test_algorithm1();
test_algorithm2();
test_algorithm3();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_algorithm();

View File

@@ -0,0 +1,20 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_algorithm1.hpp"
#include "any_types.hpp"
#include "test_algorithm_impl.hpp"
void test_algorithm1()
{
test_algorithm<
any_types::collection,jammed_auto_increment,any_types::to_int,
any_types::t1,any_types::t2,any_types::t3,
any_types::t4,any_types::t5>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_algorithm1();

View File

@@ -0,0 +1,20 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_algorithm2.hpp"
#include "base_types.hpp"
#include "test_algorithm_impl.hpp"
void test_algorithm2()
{
test_algorithm<
base_types::collection,jammed_auto_increment,base_types::to_int,
base_types::t1,base_types::t2,base_types::t3,
base_types::t4,base_types::t5>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_algorithm2();

View File

@@ -0,0 +1,20 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_algorithm3.hpp"
#include "function_types.hpp"
#include "test_algorithm_impl.hpp"
void test_algorithm3()
{
test_algorithm<
function_types::collection,jammed_auto_increment,function_types::to_int,
function_types::t1,function_types::t2,function_types::t3,
function_types::t4,function_types::t5>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_algorithm3();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_algorithm.hpp"
int main()
{
test_algorithm();
return boost::report_errors();
}

View File

@@ -0,0 +1,33 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_algorithm.hpp"
#include "test_capacity.hpp"
#include "test_comparison.hpp"
#include "test_construction.hpp"
#include "test_emplacement.hpp"
#include "test_erasure.hpp"
#include "test_insertion.hpp"
#include "test_iterators.hpp"
#include "test_registration.hpp"
int main()
{
test_algorithm();
test_capacity();
test_comparison();
test_construction();
test_emplacement();
test_erasure();
test_insertion();
test_iterators();
test_registration();
return boost::report_errors();
}

View File

@@ -0,0 +1,92 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_capacity.hpp"
#include <algorithm>
#include <boost/core/lightweight_test.hpp>
#include "any_types.hpp"
#include "base_types.hpp"
#include "function_types.hpp"
#include "test_utilities.hpp"
using namespace test_utilities;
template<typename PolyCollection,typename ValueFactory,typename... Types>
void test_capacity()
{
PolyCollection p;
const PolyCollection& cp=p;
ValueFactory v;
BOOST_TEST(cp.empty());
BOOST_TEST(cp.size()==0);
p.template register_types<Types...>();
BOOST_TEST(cp.empty());
do_((BOOST_TEST(cp.empty(typeid(Types))),0)...);
do_((BOOST_TEST(cp.template empty<Types>()),0)...);
BOOST_TEST(cp.size()==0);
do_((BOOST_TEST(cp.size(typeid(Types))==0),0)...);
do_((BOOST_TEST(cp.template size<Types>()==0),0)...);
p.reserve(10);
do_((BOOST_TEST(cp.capacity(typeid(Types))>=10),0)...);
do_((BOOST_TEST(
cp.template capacity<Types>()==cp.capacity(typeid(Types))),0)...);
do_((p.reserve(typeid(Types),20),0)...);
do_((BOOST_TEST(cp.capacity(typeid(Types))>=20),0)...);
do_((p.template reserve<Types>(30),0)...);
do_((BOOST_TEST(cp.template capacity<Types>()>=30),0)...);
fill<constraints<>,Types...>(p,v,30);
BOOST_TEST(cp.size()==30*sizeof...(Types));
do_((BOOST_TEST(cp.size(typeid(Types))==30),0)...);
do_((BOOST_TEST(cp.template size<Types>()==cp.size(typeid(Types))),0)...);
auto min_capacity=[&]{
return (std::min)({cp.template capacity<Types>()...});
};
p.reserve(min_capacity()+1);
BOOST_TEST(cp.size()==30*sizeof...(Types));
auto c=min_capacity();
p.shrink_to_fit();
BOOST_TEST(c>=min_capacity());
c=min_capacity();
do_((p.erase(cp.template begin<Types>()),0)...);
BOOST_TEST(c==min_capacity());
do_((p.shrink_to_fit(typeid(Types)),0)...);
BOOST_TEST(c>=min_capacity());
c=min_capacity();
p.clear();
do_((p.template shrink_to_fit<Types>(),0)...);
BOOST_TEST(c>=min_capacity());
}
void test_capacity()
{
test_capacity<
any_types::collection,auto_increment,
any_types::t1,any_types::t2,any_types::t3,
any_types::t4,any_types::t5>();
test_capacity<
base_types::collection,auto_increment,
base_types::t1,base_types::t2,base_types::t3,
base_types::t4,base_types::t5>();
test_capacity<
function_types::collection,auto_increment,
function_types::t1,function_types::t2,function_types::t3,
function_types::t4,function_types::t5>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_capacity();

View File

@@ -0,0 +1,16 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_capacity.hpp"
int main()
{
test_capacity();
return boost::report_errors();
}

View File

@@ -0,0 +1,156 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_comparison.hpp"
#include <boost/core/lightweight_test.hpp>
#include "any_types.hpp"
#include "base_types.hpp"
#include "function_types.hpp"
#include "test_utilities.hpp"
using namespace test_utilities;
template<typename PolyCollection,typename ValueFactory,typename... Types>
void test_comparison()
{
{
PolyCollection p1,p2;
const PolyCollection& cp1=p1;
const PolyCollection& cp2=p2;
BOOST_TEST(cp1==cp1);
BOOST_TEST(!(cp1!=cp1));
BOOST_TEST(cp1==cp2);
BOOST_TEST(!(cp1!=cp2));
}
{
PolyCollection p1,p2;
const PolyCollection& cp1=p1;
const PolyCollection& cp2=p2;
ValueFactory v;
fill<
constraints<is_not_equality_comparable>,
Types...
>(p1,v,2);
BOOST_TEST(!(cp1==cp2));
BOOST_TEST(cp1!=cp2);
}
{
PolyCollection p1,p2;
const PolyCollection& cp1=p1;
const PolyCollection& cp2=p2;
ValueFactory v;
p1.template register_types<Types...>();
fill<
constraints<is_not_equality_comparable>,
Types...
>(p1,v,2);
BOOST_TEST(!(cp1==cp2));
BOOST_TEST(cp1!=cp2);
}
{
PolyCollection p1,p2;
const PolyCollection& cp1=p1;
const PolyCollection& cp2=p2;
ValueFactory v;
fill<
constraints<is_not_equality_comparable>,
Types...
>(p1,v,1);
fill<
constraints<is_not_equality_comparable>,
Types...
>(p2,v,2);
BOOST_TEST(!(cp1==cp2));
BOOST_TEST(cp1!=cp2);
}
{
using not_equality_comparable=
boost::poly_collection::not_equality_comparable;
PolyCollection p1,p2;
const PolyCollection& cp1=p1;
const PolyCollection& cp2=p2;
ValueFactory v;
fill<
constraints<is_not_equality_comparable>,
Types...
>(p1,v,2);
fill<
constraints<is_not_equality_comparable>,
Types...
>(p2,v,2);
check_throw<not_equality_comparable>(
[&]{(void)(cp1==cp2);},
[&]{(void)(cp1!=cp2);});
}
{
PolyCollection p1,p2;
const PolyCollection& cp1=p1;
const PolyCollection& cp2=p2;
ValueFactory v;
fill<
constraints<is_not_equality_comparable>,
Types...
>(p1,v,2);
fill<
constraints<is_equality_comparable,is_copy_constructible>,
Types...
>(p2,v,2);
p1.insert(p2.begin(),p2.end());
BOOST_TEST(!(cp1==cp2));
BOOST_TEST(cp1!=cp2);
}
{
PolyCollection p1,p2;
const PolyCollection& cp1=p1;
const PolyCollection& cp2=p2;
ValueFactory v;
p1.template register_types<Types...>();
fill<
constraints<is_equality_comparable,is_copy_constructible>,
Types...
>(p2,v,2);
p1.insert(p2.begin(),p2.end());
BOOST_TEST(cp1==cp2);
BOOST_TEST(!(cp1!=cp2));
p1.erase(p1.begin());
BOOST_TEST(!(cp1==cp2));
BOOST_TEST(cp1!=cp2);
}
}
void test_comparison()
{
test_comparison<
any_types::collection,auto_increment,
any_types::t1,any_types::t2,any_types::t3,
any_types::t4,any_types::t5>();
test_comparison<
base_types::collection,auto_increment,
base_types::t1,base_types::t2,base_types::t3,
base_types::t4,base_types::t5>();
test_comparison<
function_types::collection,auto_increment,
function_types::t1,function_types::t2,function_types::t3,
function_types::t4,function_types::t5>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_comparison();

View File

@@ -0,0 +1,16 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_comparison.hpp"
int main()
{
test_comparison();
return boost::report_errors();
}

View File

@@ -0,0 +1,263 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_construction.hpp"
#include <algorithm>
#include <boost/config.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/relaxed.hpp>
#include <scoped_allocator>
#include <utility>
#include <vector>
#include "any_types.hpp"
#include "base_types.hpp"
#include "function_types.hpp"
#include "test_utilities.hpp"
using namespace test_utilities;
template<typename PolyCollection,typename ValueFactory,typename... Types>
void test_construction()
{
{
PolyCollection p;
const PolyCollection& cp=p;
ValueFactory v;
fill<
constraints<is_equality_comparable,is_copy_constructible>,
Types...
>(p,v,2);
{
PolyCollection p2{cp};
BOOST_TEST(p2==p);
}
{
PolyCollection p2;
p2=cp;
BOOST_TEST(p2==p);
}
{
PolyCollection p2{cp};
auto d2=get_layout_data<Types...>(p2);
PolyCollection p3{std::move(p2)};
auto d3=get_layout_data<Types...>(p3);
BOOST_TEST(d2==d3);
BOOST_TEST(p2.empty());
do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...);
}
{
PolyCollection p2{cp};
auto d2=get_layout_data<Types...>(p2);
PolyCollection p3;
p3={std::move(p2)};
auto d3=get_layout_data<Types...>(p3);
BOOST_TEST(d2==d3);
BOOST_TEST(p2.empty());
do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...);
}
{
PolyCollection p2{cp.begin(),cp.end()};
BOOST_TEST(p2==p);
}
{
using type=first_of<
constraints<is_equality_comparable,is_copy_constructible>,
Types...>;
PolyCollection p2{cp.template begin<type>(),cp.template end<type>()};
BOOST_TEST(
p2.size()==cp.template size<type>()&&
std::equal(
p2.template begin<type>(),p2.template end<type>(),
cp.template begin<type>()));
}
}
{
using rooted_poly_collection=
realloc_poly_collection<PolyCollection,rooted_allocator>;
using allocator_type=typename rooted_poly_collection::allocator_type;
allocator_type root1{0},root2{0};
rooted_poly_collection p{root1};
const rooted_poly_collection& cp=p;
ValueFactory v;
fill<
constraints<is_equality_comparable,is_copy_constructible>,
Types...
>(p,v,2);
{
rooted_poly_collection p2{cp,root2};
BOOST_TEST(p2==p);
BOOST_TEST(p2.get_allocator()==root2);
}
{
rooted_poly_collection p2{root2};
p2=cp;
BOOST_TEST(p2==p);
BOOST_TEST(p2.get_allocator().root==&root2);
}
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900)
/* Limitations from libstdc++-v3 make move construction with allocator
* decay to copy construction with allocator.
*/
#else
{
rooted_poly_collection p2{cp};
auto d2=get_layout_data<Types...>(p2);
rooted_poly_collection p3{std::move(p2),root2};
auto d3=get_layout_data<Types...>(p3);
BOOST_TEST(d2==d3);
BOOST_TEST(p2.empty());
do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...);
BOOST_TEST(p3.get_allocator().root==&root2);
}
#endif
{
rooted_poly_collection p2{cp};
auto d2=get_layout_data<Types...>(p2);
rooted_poly_collection p3{root2};
p3=std::move(p2);
auto d3=get_layout_data<Types...>(p3);
BOOST_TEST(d2==d3);
BOOST_TEST(p2.empty());
do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...);
#if BOOST_WORKAROUND(BOOST_MSVC,<=1900)||\
BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900)
#else
BOOST_TEST(p3.get_allocator().root==&root1);
#endif
}
}
{
using not_copy_constructible=
boost::poly_collection::not_copy_constructible;
PolyCollection p;
const PolyCollection& cp=p;
ValueFactory v;
fill<
constraints<is_equality_comparable,is_not_copy_constructible>,
Types...
>(p,v,2);
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900)
/* std::unordered_map copy construction and assigment crash when elements
* throw on copy construction.
*/
static_assert(
sizeof(not_copy_constructible)>0,""); /* Wunused-local-typedefs */
(void)cp; /* Wunused-variable */
#else
check_throw<not_copy_constructible>([&]{
PolyCollection p2{cp};
(void)p2;
});
check_throw<not_copy_constructible>([&]{
PolyCollection p2;
p2=cp;
});
#endif
{
PolyCollection p2{std::move(p)};
BOOST_TEST(!p2.empty());
BOOST_TEST(p.empty());
do_((BOOST_TEST(!p.template is_registered<Types>()),0)...);
p={std::move(p2)};
BOOST_TEST(!p.empty());
BOOST_TEST(p2.empty());
do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...);
}
}
{
PolyCollection p1,p2;
ValueFactory v;
fill<constraints<>,Types...>(p1,v,2);
auto d1=get_layout_data<Types...>(p1),
d2=get_layout_data<Types...>(p2);
p1.swap(p2);
auto e1=get_layout_data<Types...>(p1),
e2=get_layout_data<Types...>(p2);
BOOST_TEST(d1==e2);
BOOST_TEST(d2==e1);
do_((BOOST_TEST(!p1.template is_registered<Types>()),0)...);
using std::swap;
swap(p1,p2);
auto f1=get_layout_data<Types...>(p1),
f2=get_layout_data<Types...>(p2);
BOOST_TEST(e1==f2);
BOOST_TEST(e2==f1);
do_((BOOST_TEST(!p2.template is_registered<Types>()),0)...);
}
}
void test_scoped_allocator()
{
using vector_allocator=rooted_allocator<char>;
using vector=std::vector<char,vector_allocator>;
using concept_=boost::type_erasure::relaxed;
using element_allocator=rooted_allocator<
boost::poly_collection::any_collection_value_type<concept_>
>;
using collection_allocator=std::scoped_allocator_adaptor<
element_allocator,
vector_allocator
>;
using poly_collection=
boost::any_collection<concept_,collection_allocator>;
element_allocator roote{0};
vector_allocator rootv{0};
collection_allocator al{roote,rootv};
poly_collection p{al};
p.emplace<vector>();
auto& s=boost::type_erasure::any_cast<vector&>(*p.begin());
BOOST_TEST(p.get_allocator().root==&roote);
#if BOOST_WORKAROUND(BOOST_MSVC,>=1910)
/* https://connect.microsoft.com/VisualStudio/feedback/details/3136309 */
#else
BOOST_TEST(s.get_allocator().root==&rootv);
#endif
}
void test_construction()
{
test_construction<
any_types::collection,auto_increment,
any_types::t1,any_types::t2,any_types::t3,
any_types::t4,any_types::t5>();
test_construction<
base_types::collection,auto_increment,
base_types::t1,base_types::t2,base_types::t3,
base_types::t4,base_types::t5>();
test_construction<
function_types::collection,auto_increment,
function_types::t1,function_types::t2,function_types::t3,
function_types::t4,function_types::t5>();
test_scoped_allocator();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_construction();

View File

@@ -0,0 +1,16 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_construction.hpp"
int main()
{
test_construction();
return boost::report_errors();
}

View File

@@ -0,0 +1,121 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_emplacement.hpp"
#include <boost/core/lightweight_test.hpp>
#include "any_types.hpp"
#include "base_types.hpp"
#include "function_types.hpp"
#include "test_utilities.hpp"
using namespace test_utilities;
template<typename PolyCollection,typename ValueFactory,typename... Types>
void test_emplacement()
{
{
using type=first_of<
constraints<
is_constructible_from_int,is_not_copy_constructible,
is_not_copy_assignable,
is_equality_comparable
>,
Types...
>;
using iterator=typename PolyCollection::iterator;
using local_base_iterator=typename PolyCollection::local_base_iterator;
using local_iterator=
typename PolyCollection::template local_iterator<type>;
PolyCollection p;
iterator it=p.template emplace<type>(4);
BOOST_TEST(*p.template begin<type>()==type{4});
BOOST_TEST(&*it==&*p.begin(typeid(type)));
iterator it2=p.template emplace_hint<type>(it,3);
BOOST_TEST(*p.template begin<type>()==type{3});
BOOST_TEST(&*it2==&*p.begin(typeid(type)));
iterator it3=p.template emplace_hint<type>(p.cend(),5);
BOOST_TEST(*(p.template end<type>()-1)==type{5});
BOOST_TEST(&*it3==&*(p.end(typeid(type))-1));
local_base_iterator lbit=
p.template emplace_pos<type>(p.begin(typeid(type)),2);
BOOST_TEST(*static_cast<local_iterator>(lbit)==type{2});
BOOST_TEST(lbit==p.begin(typeid(type)));
local_base_iterator lbit2=
p.template emplace_pos<type>(p.cend(typeid(type)),6);
BOOST_TEST(*static_cast<local_iterator>(lbit2)==type{6});
BOOST_TEST(lbit2==p.end(typeid(type))-1);
local_iterator lit=p.emplace_pos(p.template begin<type>(),1);
BOOST_TEST(*lit==type{1});
BOOST_TEST(lit==p.template begin<type>());
local_iterator lit2=p.emplace_pos(p.template cend<type>(),7);
BOOST_TEST(*lit2==type{7});
BOOST_TEST(lit2==p.template end<type>()-1);
}
{
using type=first_of<
constraints<is_default_constructible>,
Types...
>;
PolyCollection p;
p.template emplace<type>();
p.template emplace_hint<type>(p.begin());
p.template emplace_hint<type>(p.cend());
p.template emplace_pos<type>(p.begin(typeid(type)));
p.template emplace_pos<type>(p.cend(typeid(type)));
p.emplace_pos(p.template begin<type>());
p.emplace_pos(p.template cend<type>());
BOOST_TEST(p.size()==7);
}
{
using type=first_of<
constraints<is_not_copy_constructible>,
Types...
>;
PolyCollection p;
ValueFactory v;
p.template emplace<type>(v.template make<type>());
p.template emplace_hint<type>(p.begin(),v.template make<type>());
p.template emplace_hint<type>(p.cend(),v.template make<type>());
p.template emplace_pos<type>(
p.begin(typeid(type)),v.template make<type>());
p.template emplace_pos<type>(
p.cend(typeid(type)),v.template make<type>());
p.emplace_pos(p.template begin<type>(),v.template make<type>());
p.emplace_pos(p.template cend<type>(),v.template make<type>());
BOOST_TEST(p.size()==7);
}
}
void test_emplacement()
{
test_emplacement<
any_types::collection,auto_increment,
any_types::t1,any_types::t2,any_types::t3,
any_types::t4,any_types::t5>();
test_emplacement<
base_types::collection,auto_increment,
base_types::t1,base_types::t2,base_types::t3,
base_types::t4,base_types::t5>();
test_emplacement<
function_types::collection,auto_increment,
function_types::t1,function_types::t2,function_types::t3,
function_types::t4,function_types::t5>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_emplacement();

View File

@@ -0,0 +1,16 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_emplacement.hpp"
int main()
{
test_emplacement();
return boost::report_errors();
}

View File

@@ -0,0 +1,151 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_erasure.hpp"
#include <boost/core/lightweight_test.hpp>
#include <iterator>
#include "any_types.hpp"
#include "base_types.hpp"
#include "function_types.hpp"
#include "test_utilities.hpp"
using namespace test_utilities;
template<typename Type,typename PolyCollection>
void test_local_erase(const PolyCollection& p2)
{
using size_type=typename PolyCollection::size_type;
for(size_type i=0;i<p2.template size<Type>();++i){
PolyCollection p=p2;
auto it=p.erase(p.template cbegin<Type>()+i);
BOOST_TEST(it-p.template begin<Type>()==(std::ptrdiff_t)i);
BOOST_TEST(p.template size<Type>()==p2.template size<Type>()-1);
}
}
template<typename Type,typename PolyCollection>
void test_local_range_erase(const PolyCollection& p2)
{
using size_type=typename PolyCollection::size_type;
for(size_type i=0;i<=p2.template size<Type>();++i){
for(size_type j=i;j<=p2.template size<Type>();++j){
PolyCollection p=p2;
auto first=p.template cbegin<Type>()+i,
last=p.template cbegin<Type>()+j;
auto it=p.erase(first,last);
BOOST_TEST(it-p.template begin<Type>()==(std::ptrdiff_t)i);
BOOST_TEST(p.template size<Type>()==p2.template size<Type>()-(j-i));
}
}
}
template<typename Type,typename PolyCollection>
void test_local_clear(const PolyCollection& p2)
{
PolyCollection p=p2;
p.template clear<Type>();
BOOST_TEST(p.template empty<Type>());
BOOST_TEST(p.size()==p2.size()-p2.template size<Type>());
}
template<typename PolyCollection,typename ValueFactory,typename... Types>
void test_erasure()
{
using size_type=typename PolyCollection::size_type;
PolyCollection p,p2;
ValueFactory v;
fill<constraints<is_copy_constructible>,Types...>(p2,v,5);
auto sit=p2.segment_traversal().begin();
p2.clear(sit->type_info());
++sit;++sit;
p2.clear(sit->type_info());
for(size_type i=0;i<p2.size();++i){
p=p2;
auto it=p.erase(std::next(p.cbegin(),i));
BOOST_TEST(std::distance(p.begin(),it)==(std::ptrdiff_t)i);
BOOST_TEST(p.size()==p2.size()-1);
}
for(auto s:p2.segment_traversal()){
auto& info=s.type_info();
for(size_type i=0;i<p2.size(info);++i){
p=p2;
auto it=p.erase(p.cbegin(info)+i);
BOOST_TEST(it-p.begin(info)==(std::ptrdiff_t)i);
BOOST_TEST(p.size(info)==p2.size(info)-1);
}
}
do_((
p2.template is_registered<Types>()?test_local_erase<Types>(p2),0:0)...);
for(size_type i=0;i<=p2.size();++i){
for(size_type j=i;j<=p2.size();++j){
p=p2;
auto first=std::next(p.cbegin(),i),
last=std::next(p.cbegin(),j);
auto it=p.erase(first,last);
BOOST_TEST(std::distance(p.begin(),it)==(std::ptrdiff_t)i);
BOOST_TEST(p.size()==p2.size()-(j-i));
}
}
for(auto s:p2.segment_traversal()){
auto& info=s.type_info();
for(size_type i=0;i<=p2.size(info);++i){
for(size_type j=i;j<=p2.size(info);++j){
p=p2;
auto first=p.cbegin(info)+i,
last=p.cbegin(info)+j;
auto it=p.erase(first,last);
BOOST_TEST(it-p.begin(info)==(std::ptrdiff_t)i);
BOOST_TEST(p.size(info)==p2.size(info)-(j-i));
}
}
}
do_((p2.template is_registered<Types>()?
test_local_range_erase<Types>(p2),0:0)...);
p=p2;
p.clear();
BOOST_TEST(p.empty());
for(auto s:p2.segment_traversal()){
auto& info=s.type_info();
p=p2;
p.clear(info);
BOOST_TEST(p.empty(info));
BOOST_TEST(p.size()==p2.size()-p2.size(info));
}
do_((p2.template is_registered<Types>()?
test_local_clear<Types>(p2),0:0)...);
}
void test_erasure()
{
test_erasure<
any_types::collection,auto_increment,
any_types::t1,any_types::t2,any_types::t3,
any_types::t4,any_types::t5>();
test_erasure<
base_types::collection,auto_increment,
base_types::t1,base_types::t2,base_types::t3,
base_types::t4,base_types::t5>();
test_erasure<
function_types::collection,auto_increment,
function_types::t1,function_types::t2,function_types::t3,
function_types::t4,function_types::t5>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_erasure();

View File

@@ -0,0 +1,16 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_erasure.hpp"
int main()
{
test_erasure();
return boost::report_errors();
}

View File

@@ -0,0 +1,354 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_insertion.hpp"
#include <algorithm>
#include <boost/core/lightweight_test.hpp>
#include <numeric>
#include <vector>
#include "any_types.hpp"
#include "base_types.hpp"
#include "function_types.hpp"
#include "test_utilities.hpp"
using namespace test_utilities;
template<typename PolyCollection,typename ValueFactory,typename... Types>
void test_insertion()
{
{
using unregistered_type=boost::poly_collection::unregistered_type;
using type=first_of<constraints<is_copy_constructible>,Types...>;
PolyCollection p,p2;
ValueFactory v;
p2.insert(v.template make<type>());
check_throw<unregistered_type>(
[&]{p.insert(*p2.begin());},
[&]{p.insert(p.end(),*p2.begin());},
[&]{p.insert(p.cend(),*p2.begin());},
[&]{p.insert(
external_iterator(p2.begin()),external_iterator(p2.end()));},
[&]{p.insert(
p.end(),
external_iterator(p2.begin()),external_iterator(p2.end()));},
[&]{p.insert(
p.cend(),
external_iterator(p2.begin()),external_iterator(p2.end()));});
}
{
using not_copy_constructible=
boost::poly_collection::not_copy_constructible;
using type=first_of<constraints<is_not_copy_constructible>,Types...>;
PolyCollection p,p2;
ValueFactory v;
p.template register_types<type>();
p2.insert(v.template make<type>());
auto p2b=external_iterator(p2.begin()),
p2e=external_iterator(p2.end());
auto p2lb=external_iterator(p2.template begin<type>()),
p2le=external_iterator(p2.template end<type>());
check_throw<not_copy_constructible>(
[&]{p.insert(*p2.begin());},
[&]{p.insert(p.end(),*p2.begin());},
[&]{p.insert(p.cend(),*p2.cbegin());},
[&]{p.insert(p.end(typeid(type)),*p2.begin());},
[&]{p.insert(p.cend(typeid(type)),*p2.begin());},
[&]{p.insert(p.template end<type>(),*p2.begin());},
[&]{p.insert(p.template cend<type>(),*p2.begin());},
[&]{p.insert(p2b,p2e);},
[&]{p.insert(p2lb,p2le);},
[&]{p.insert(p2.begin(),p2.end());},
[&]{p.insert(p2.begin(typeid(type)),p2.end(typeid(type)));},
[&]{p.insert(p2.template begin<type>(),p2.template end<type>());},
[&]{p.insert(p.end(),p2b,p2e);},
[&]{p.insert(p.end(),p2lb,p2le);},
[&]{p.insert(p.end(),p2.begin(),p2.end());},
[&]{p.insert(p.end(),p2.begin(typeid(type)),p2.end(typeid(type)));},
[&]{p.insert(
p.end(),p2.template begin<type>(),p2.template end<type>());},
[&]{p.insert(p.cend(),p2b,p2e);},
[&]{p.insert(p.cend(),p2lb,p2le);},
[&]{p.insert(p.cend(),p2.begin(),p2.end());},
[&]{p.insert(p.cend(),p2.begin(typeid(type)),p2.end(typeid(type)));},
[&]{p.insert(
p.cend(),p2.template begin<type>(),p2.template end<type>());},
[&]{p.insert(p.end(typeid(type)),p2b,p2e);},
[&]{p.insert(p.cend(typeid(type)),p2b,p2e);},
[&]{p.insert(p.template end<type>(),p2b,p2e);},
[&]{p.insert(p.template cend<type>(),p2b,p2e);});
}
{
PolyCollection p;
ValueFactory v;
fill<constraints<>,Types...>(p,v,2);
do_((BOOST_TEST(
is_last(
p,typeid(Types),
p.insert(constref_if_copy_constructible(v.template make<Types>())))
),0)...);
}
{
PolyCollection p;
ValueFactory v;
fill<constraints<>,Types...>(p,v,2);
auto& info=p.segment_traversal().begin()->type_info();
do_((BOOST_TEST(
info==typeid(Types)?
is_first(
p,typeid(Types),
p.insert(
p.cbegin(),
constref_if_copy_constructible(v.template make<Types>()))):
is_last(
p,typeid(Types),
p.insert(
p.cbegin(),
constref_if_copy_constructible(v.template make<Types>())))
),0)...);
do_((BOOST_TEST(
is_first(
p,typeid(Types),
p.insert(
p.cbegin(typeid(Types)),
constref_if_copy_constructible(v.template make<Types>())))
),0)...);
do_((BOOST_TEST(
is_first<Types>(
p,
p.insert(
p.template cbegin<Types>(),
constref_if_copy_constructible(v.template make<Types>())))
),0)...);
}
{
PolyCollection p,p2;
ValueFactory v;
p.template register_types<Types...>();
p2.template register_types<Types...>();
fill<
constraints<is_copy_constructible,is_equality_comparable>,
Types...
>(p2,v,2);
p.insert(external_iterator(p2.begin()),external_iterator(p2.end()));
BOOST_TEST(p==p2);
p.clear();
p.insert(p2.begin(),p2.end());
BOOST_TEST(p==p2);
p.clear();
p.insert(p2.cbegin(),p2.cend());
BOOST_TEST(p==p2);
p.clear();
for(auto s:p2.segment_traversal()){
p.insert(s.begin(),s.end());
BOOST_TEST(p.size()==p2.size(s.type_info()));
p.clear();
p.insert(s.cbegin(),s.cend());
BOOST_TEST(p.size()==p2.size(s.type_info()));
p.clear();
}
do_((
p.insert(
external_iterator(p2.template begin<Types>()),
external_iterator(p2.template end<Types>())),
BOOST_TEST(p.size()==p2.template size<Types>()),
p.clear()
,0)...);
do_((
p.insert(p2.template begin<Types>(),p2.template end<Types>()),
BOOST_TEST(p.size()==p2.template size<Types>()),
p.clear()
,0)...);
do_((
p.insert(p2.template cbegin<Types>(),p2.template cend<Types>()),
BOOST_TEST(p.size()==p2.template size<Types>()),
p.clear()
,0)...);
}
{
PolyCollection p,p1,p2;
ValueFactory v;
p2.template register_types<Types...>();
fill<
constraints<is_copy_constructible,is_equality_comparable>,
Types...
>(p1,v,2);
fill<
constraints<is_copy_constructible,is_equality_comparable>,
Types...
>(p2,v,2);
auto remove_original=[](PolyCollection& p)
{
bool first=true;
for(auto s:p.segment_traversal()){
if(first)p.erase(s.end()-2,s.end()),first=false;
else p.erase(s.begin(),s.begin()+2);
}
};
p=p1;
p.insert(
p.begin(),external_iterator(p2.begin()),external_iterator(p2.end()));
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
p.insert(p.begin(),p2.begin(),p2.end());
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
p.insert(p.begin(),p2.cbegin(),p2.cend());
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
for(auto s:p2.segment_traversal())p.insert(p.begin(),s.begin(),s.end());
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
for(auto s:p2.segment_traversal())p.insert(p.begin(),s.cbegin(),s.cend());
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
do_((p.insert(
p.begin(),
external_iterator(p2.template begin<Types>()),
external_iterator(p2.template end<Types>())),0)...);
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
do_((p.insert(
p.begin(),p2.template begin<Types>(),p2.template end<Types>()),0)...);
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
do_((p.insert(
p.begin(),p2.template cbegin<Types>(),p2.template cend<Types>()),0)...);
remove_original(p);
BOOST_TEST(p==p2);
}
{
using type=first_of<
constraints<is_copy_constructible,is_equality_comparable>,
Types...
>;
PolyCollection p,p1,p2;
ValueFactory v;
fill<constraints<>,type>(p1,v,2);
fill<constraints<>,type>(p2,v,2);
auto remove_original=[](PolyCollection& p)
{
auto it=p.segment_traversal().begin()->end();
p.erase(it-2,it);
};
p=p1;
BOOST_TEST(is_first(
p,typeid(type),
p.insert(
p.begin(typeid(type)),
external_iterator(p2.begin()),external_iterator(p2.end()))));
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
BOOST_TEST(is_first(
p,typeid(type),
p.insert(
p.cbegin(typeid(type)),
external_iterator(p2.begin()),external_iterator(p2.end()))));
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
BOOST_TEST(is_first<type>(
p,
p.insert(
p.template begin<type>(),
external_iterator(p2.begin()),external_iterator(p2.end()))));
remove_original(p);
BOOST_TEST(p==p2);
p=p1;
BOOST_TEST(is_first<type>(
p,
p.insert(
p.template cbegin<type>(),
external_iterator(p2.begin()),external_iterator(p2.end()))));
remove_original(p);
BOOST_TEST(p==p2);
}
{
using type=first_of<
constraints<
is_constructible_from_int,is_not_copy_constructible,
is_equality_comparable
>,
Types...
>;
PolyCollection p;
std::vector<int> s(10);
ValueFactory v;
fill<constraints<>,type>(p,v,2);
std::iota(s.begin(),s.end(),0);
BOOST_TEST(is_first<type>(
p,
p.insert(p.template begin<type>(),s.begin(),s.end())));
BOOST_TEST(
std::equal(s.begin(),s.end(),p.template begin<type>(),
[](int x,const type& y){return type{x}==y;})
);
}
}
void test_insertion()
{
test_insertion<
any_types::collection,auto_increment,
any_types::t1,any_types::t2,any_types::t3,
any_types::t4,any_types::t5>();
test_insertion<
base_types::collection,auto_increment,
base_types::t1,base_types::t2,base_types::t3,
base_types::t4,base_types::t5>();
test_insertion<
function_types::collection,auto_increment,
function_types::t1,function_types::t2,function_types::t3,
function_types::t4,function_types::t5>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_insertion();

View File

@@ -0,0 +1,16 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_insertion.hpp"
int main()
{
test_insertion();
return boost::report_errors();
}

View File

@@ -0,0 +1,310 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_iterators.hpp"
#include <boost/core/lightweight_test.hpp>
#include <iterator>
#include <type_traits>
#include "any_types.hpp"
#include "base_types.hpp"
#include "function_types.hpp"
#include "test_utilities.hpp"
using namespace test_utilities;
template<typename Iterator>
using is_input=std::is_base_of<
std::input_iterator_tag,
typename std::iterator_traits<Iterator>::iterator_category
>;
template<typename Iterator>
using is_forward=std::is_base_of<
std::forward_iterator_tag,
typename std::iterator_traits<Iterator>::iterator_category
>;
template<typename Iterator>
using is_random_access=std::is_base_of<
std::random_access_iterator_tag,
typename std::iterator_traits<Iterator>::iterator_category
>;
template<typename Type,typename PolyCollection>
void test_iterators(PolyCollection& p)
{
using local_base_iterator=typename PolyCollection::local_base_iterator;
using const_local_base_iterator=
typename PolyCollection::const_local_base_iterator;
using local_iterator=typename PolyCollection::template local_iterator<Type>;
using const_local_iterator=
typename PolyCollection::template const_local_iterator<Type>;
using base_segment_info=typename PolyCollection::base_segment_info;
using const_base_segment_info=
typename PolyCollection::const_base_segment_info;
using const_segment_info=
typename PolyCollection::template const_segment_info<Type>;
using segment_info=typename PolyCollection::template segment_info<Type>;
static_assert(is_random_access<local_iterator>::value,
"local_iterator must be random access");
static_assert(is_random_access<const_local_iterator>::value,
"const_local_iterator must be random access");
static_assert(std::is_base_of<const_segment_info,segment_info>::value,
"segment_info must derive from const_segment_info");
{
local_iterator lit;
const_local_iterator clit,clit2(lit); /* sorry about the names */
lit=lit;
clit=clit2;
clit=lit;
}
const PolyCollection& cp=p;
std::size_t n=0;
local_base_iterator lbfirst=p.begin(typeid(Type)),
lblast=p.end(typeid(Type));
const_local_base_iterator clbfirst=cp.begin(typeid(Type)),
clblast=cp.end(typeid(Type));
local_iterator lfirst=p.template begin<Type>(),
llast=p.template end<Type>();
const_local_iterator clfirst=cp.template begin<Type>(),
cllast=cp.template end<Type>();
base_segment_info bi=p.segment(typeid(Type));
const_base_segment_info cbi=cp.segment(typeid(Type));
segment_info i=p.template segment<Type>();
const_segment_info ci=cp.template segment<Type>();
BOOST_TEST(clbfirst==cp.cbegin(typeid(Type)));
BOOST_TEST(clblast==cp.cend(typeid(Type)));
BOOST_TEST(clfirst==cp.template cbegin<Type>());
BOOST_TEST(cllast==cp.template cend<Type>());
BOOST_TEST(lbfirst==bi.begin());
BOOST_TEST(lblast==bi.end());
BOOST_TEST(clbfirst==bi.cbegin());
BOOST_TEST(clbfirst==cbi.begin());
BOOST_TEST(clblast==bi.cend());
BOOST_TEST(clblast==cbi.end());
BOOST_TEST(lfirst==i.begin());
BOOST_TEST(llast==i.end());
BOOST_TEST(clfirst==i.cbegin());
BOOST_TEST(clfirst==ci.begin());
BOOST_TEST(cllast==i.cend());
BOOST_TEST(cllast==ci.end());
for(;lbfirst!=lblast;++lbfirst,++clbfirst,++lfirst,++clfirst){
BOOST_TEST(lfirst==static_cast<local_iterator>(lbfirst));
BOOST_TEST(static_cast<local_base_iterator>(lfirst)==lbfirst);
BOOST_TEST(clfirst==static_cast<const_local_iterator>(clbfirst));
BOOST_TEST(static_cast<const_local_base_iterator>(clfirst)==clbfirst);
BOOST_TEST(clfirst==lfirst);
BOOST_TEST(&*lfirst==&*static_cast<local_iterator>(lbfirst));
BOOST_TEST(&*clfirst==&*static_cast<const_local_iterator>(clbfirst));
BOOST_TEST(&*clfirst==&*lfirst);
Type& r=p.template begin<Type>()[n];
const Type& cr=cp.template begin<Type>()[n];
BOOST_TEST(&*lfirst==&r);
BOOST_TEST(&*clfirst==&cr);
++n;
}
BOOST_TEST(clbfirst==clblast);
BOOST_TEST(lfirst==llast);
BOOST_TEST(clfirst==cllast);
BOOST_TEST(lfirst==static_cast<local_iterator>(llast));
BOOST_TEST(clfirst==static_cast<const_local_iterator>(cllast));
BOOST_TEST(clfirst==llast);
BOOST_TEST((std::ptrdiff_t)n==p.end(typeid(Type))-p.begin(typeid(Type)));
BOOST_TEST(
(std::ptrdiff_t)n==p.template end<Type>()-p.template begin<Type>());
for(auto s:p.segment_traversal()){
if(s.type_info()==typeid(Type)){
const auto& cs=s;
BOOST_TEST(
s.template begin<Type>()==
static_cast<local_iterator>(s.begin()));
BOOST_TEST(
s.template end<Type>()==
static_cast<local_iterator>(s.end()));
BOOST_TEST(
cs.template begin<Type>()==
static_cast<const_local_iterator>(cs.begin()));
BOOST_TEST(
cs.template end<Type>()==
static_cast<const_local_iterator>(cs.end()));
BOOST_TEST(
cs.template cbegin<Type>()==
static_cast<const_local_iterator>(cs.cbegin()));
BOOST_TEST(
cs.template cend<Type>()==
static_cast<const_local_iterator>(cs.cend()));
}
}
}
template<typename PolyCollection,typename ValueFactory,typename... Types>
void test_iterators()
{
using value_type=typename PolyCollection::value_type;
using iterator=typename PolyCollection::iterator;
using const_iterator=typename PolyCollection::const_iterator;
using local_base_iterator=typename PolyCollection::local_base_iterator;
using const_local_base_iterator=
typename PolyCollection::const_local_base_iterator;
using const_base_segment_info=
typename PolyCollection::const_base_segment_info;
using base_segment_info=typename PolyCollection::base_segment_info;
using base_segment_info_iterator=
typename PolyCollection::base_segment_info_iterator;
using const_base_segment_info_iterator=
typename PolyCollection::const_base_segment_info_iterator;
using const_segment_traversal_info=
typename PolyCollection::const_segment_traversal_info;
using segment_traversal_info=
typename PolyCollection::segment_traversal_info;
static_assert(is_forward<iterator>::value,
"iterator must be forward");
static_assert(is_forward<const_iterator>::value,
"const_iterator must be forward");
static_assert(is_random_access<local_base_iterator>::value,
"local_base_iterator must be random access");
static_assert(is_random_access<const_local_base_iterator>::value,
"const_local_base_iterator must be random access");
static_assert(std::is_base_of<
const_base_segment_info,base_segment_info>::value,
"base_segment_info must derive from const_base_segment_info");
static_assert(is_input<base_segment_info_iterator>::value,
"base_segment_info_iterator must be input");
static_assert(is_input<const_base_segment_info_iterator>::value,
"const_base_segment_info_iterator must be input");
static_assert(std::is_base_of<
const_segment_traversal_info,segment_traversal_info>::value,
"const_segment_traversal_info must derive "\
"from segment_traversal_info");
{
iterator it;
const_iterator cit,cit2(it);
local_base_iterator lbit;
const_local_base_iterator clbit,clbit2(lbit);
base_segment_info_iterator sit;
const_base_segment_info_iterator csit,csit2(csit);
it=it;
cit=cit2;
cit=it;
lbit=lbit;
clbit=clbit2;
clbit=lbit;
sit=sit;
csit=csit2;
csit=sit;
}
PolyCollection p;
const PolyCollection& cp=p;
ValueFactory v;
fill<constraints<>,Types...>(p,v,2);
{
std::size_t n=0;
iterator first=p.begin(),last=p.end();
const_iterator cfirst=cp.begin(),clast=cp.end();
BOOST_TEST(cfirst==cp.cbegin());
BOOST_TEST(clast==cp.cend());
for(;first!=last;++first,++cfirst){
BOOST_TEST(first==cfirst);
BOOST_TEST(&*first==&*cfirst);
++n;
}
BOOST_TEST(cfirst==clast);
BOOST_TEST(last==clast);
BOOST_TEST(n==p.size());
}
{
std::size_t n=0;
base_segment_info_iterator first=p.segment_traversal().begin(),
last=p.segment_traversal().end();
const_base_segment_info_iterator cfirst=cp.segment_traversal().begin(),
clast=cp.segment_traversal().end();
BOOST_TEST(cfirst==cp.segment_traversal().cbegin());
BOOST_TEST(clast==cp.segment_traversal().cend());
for(;first!=last;++first,++cfirst){
BOOST_TEST(first==cfirst);
std::size_t m=0;
local_base_iterator lbfirst=first->begin(),lblast=first->end();
const_local_base_iterator clbfirst=cfirst->begin(),clblast=cfirst->end();
BOOST_TEST(clbfirst==cfirst->cbegin());
BOOST_TEST(clblast==cfirst->cend());
BOOST_TEST(lbfirst==p.begin(first->type_info()));
BOOST_TEST(lblast==p.end(first->type_info()));
BOOST_TEST(clbfirst==cp.begin(first->type_info()));
BOOST_TEST(clblast==cp.end(first->type_info()));
BOOST_TEST(clbfirst==cp.cbegin(first->type_info()));
BOOST_TEST(clblast==cp.cend(first->type_info()));
for(;lbfirst!=lblast;++lbfirst,++clbfirst){
BOOST_TEST(lbfirst==clbfirst);
BOOST_TEST(&*lbfirst==&*clbfirst);
value_type& r=first->begin()[m];
const value_type& cr=cfirst->begin()[m];
BOOST_TEST(&*lbfirst==&r);
BOOST_TEST(&*clbfirst==&cr);
++m;
}
BOOST_TEST(clbfirst==clblast);
BOOST_TEST(lblast==clblast);
BOOST_TEST((std::ptrdiff_t)m==first->end()-first->begin());
BOOST_TEST((std::ptrdiff_t)m==cfirst->end()-cfirst->begin());
BOOST_TEST((std::ptrdiff_t)m==cfirst->cend()-cfirst->cbegin());
n+=m;
}
BOOST_TEST(cfirst==clast);
BOOST_TEST(last==clast);
BOOST_TEST(n==p.size());
}
do_((test_iterators<Types>(p),0)...);
}
void test_iterators()
{
test_iterators<
any_types::collection,auto_increment,
any_types::t1,any_types::t2,any_types::t3,
any_types::t4,any_types::t5>();
test_iterators<
base_types::collection,auto_increment,
base_types::t1,base_types::t2,base_types::t3,
base_types::t4,base_types::t5>();
test_iterators<
function_types::collection,auto_increment,
function_types::t1,function_types::t2,function_types::t3,
function_types::t4,function_types::t5>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_iterators();

View File

@@ -0,0 +1,16 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_iterators.hpp"
int main()
{
test_iterators();
return boost::report_errors();
}

View File

@@ -0,0 +1,119 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include "test_registration.hpp"
#include <boost/core/lightweight_test.hpp>
#include <iterator>
#include "any_types.hpp"
#include "base_types.hpp"
#include "function_types.hpp"
#include "test_utilities.hpp"
using namespace test_utilities;
template<typename PolyCollection,typename Type>
void test_registration()
{
using unregistered_type=boost::poly_collection::unregistered_type;
{
PolyCollection p;
const PolyCollection& cp=p;
BOOST_TEST(!p.is_registered(typeid(Type)));
BOOST_TEST(!p.template is_registered<Type>());
check_throw<unregistered_type>(
[&]{(void)p.begin(typeid(Type));},
[&]{(void)p.end(typeid(Type));},
[&]{(void)cp.begin(typeid(Type));},
[&]{(void)cp.end(typeid(Type));},
[&]{(void)p.cbegin(typeid(Type));},
[&]{(void)p.cend(typeid(Type));},
[&]{(void)p.template begin<Type>();},
[&]{(void)p.template end<Type>();},
[&]{(void)cp.template begin<Type>();},
[&]{(void)cp.template end<Type>();},
[&]{(void)p.template cbegin<Type>();},
[&]{(void)p.template cend<Type>();},
[&]{(void)p.segment(typeid(Type));},
[&]{(void)cp.segment(typeid(Type));},
[&]{(void)p.template segment<Type>();},
[&]{(void)cp.template segment<Type>();},
[&]{(void)cp.empty(typeid(Type));},
[&]{(void)cp.size(typeid(Type));},
[&]{(void)cp.max_size(typeid(Type));},
[&]{(void)p.reserve(typeid(Type),0);},
[&]{(void)cp.capacity(typeid(Type));},
[&]{(void)p.shrink_to_fit(typeid(Type));},
[&]{(void)p.clear(typeid(Type));},
[&]{(void)cp.template empty<Type>();},
[&]{(void)cp.template size<Type>();},
[&]{(void)cp.template max_size<Type>();},
/* reserve<Type> omitted as it actually registers the type */
[&]{(void)cp.template capacity<Type>();},
[&]{(void)p.template shrink_to_fit<Type>();},
[&]{(void)p.template clear<Type>();});
p.register_types();
p.template register_types<>();
BOOST_TEST(!p.is_registered(typeid(Type)));
p.template register_types<Type>();
BOOST_TEST(p.is_registered(typeid(Type)));
BOOST_TEST(p.template is_registered<Type>());
(void)p.end(typeid(Type));
(void)cp.begin(typeid(Type));
(void)cp.end(typeid(Type));
(void)p.cbegin(typeid(Type));
(void)p.cend(typeid(Type));
(void)p.template begin<Type>();
(void)p.template end<Type>();
(void)cp.template begin<Type>();
(void)cp.template end<Type>();
(void)cp.template cbegin<Type>();
(void)cp.template cend<Type>();
(void)cp.empty(typeid(Type));
(void)cp.size(typeid(Type));
(void)cp.max_size(typeid(Type));
(void)p.reserve(typeid(Type),0);
(void)cp.capacity(typeid(Type));
(void)p.shrink_to_fit(typeid(Type));
(void)p.clear(typeid(Type));
(void)cp.template empty<Type>();
(void)cp.template size<Type>();
(void)cp.template max_size<Type>();
/* reserve<Type> omitted */
(void)cp.template capacity<Type>();
(void)p.template shrink_to_fit<Type>();
(void)p.template clear<Type>();
}
{
PolyCollection p;
p.template reserve<Type>(0);
BOOST_TEST(p.is_registered(typeid(Type)));
}
{
PolyCollection p;
p.template register_types<Type,Type,Type>();
BOOST_TEST(p.is_registered(typeid(Type)));
BOOST_TEST(
std::distance(
p.segment_traversal().begin(),p.segment_traversal().end())==1);
}
}
void test_registration()
{
test_registration<any_types::collection,any_types::t1>();
test_registration<base_types::collection,base_types::t1>();
test_registration<function_types::collection,function_types::t1>();
}

View File

@@ -0,0 +1,9 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
void test_registration();

View File

@@ -0,0 +1,16 @@
/* Copyright 2016 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#include <boost/core/lightweight_test.hpp>
#include "test_registration.hpp"
int main()
{
test_registration();
return boost::report_errors();
}

View File

@@ -0,0 +1,385 @@
/* Copyright 2016-2017 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/poly_collection for library home page.
*/
#ifndef BOOST_POLY_COLLECTION_TEST_TEST_UTILITIES_HPP
#define BOOST_POLY_COLLECTION_TEST_TEST_UTILITIES_HPP
#if defined(_MSC_VER)
#pragma once
#endif
#include <array>
#include <boost/core/lightweight_test.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/type_traits/has_equal_to.hpp>
#include <iterator>
#include <memory>
#include <type_traits>
#include <typeinfo>
#include <utility>
namespace test_utilities{
template<typename... Values>
void do_(Values...){}
template<typename Exception,typename F>
void check_throw_case(F f)
{
try{
(void)f();
BOOST_TEST(false);
}
catch(const Exception&){}
catch(...){BOOST_TEST(false);}
}
template<typename Exception,typename... Fs>
void check_throw(Fs... f)
{
do_((check_throw_case<Exception>(f),0)...);
}
template<typename F1,typename F2>
struct compose_class
{
F1 f1;
F2 f2;
compose_class(const F1& f1,const F2& f2):f1(f1),f2(f2){}
template<typename T,typename... Args>
auto operator()(T&& x,Args&&... args)
->decltype(std::declval<F2>()(std::declval<F1>()(
std::forward<T>(x)),std::forward<Args>(args)...))
{
return f2(f1(std::forward<T>(x)),std::forward<Args>(args)...);
}
};
template<typename F1,typename F2>
compose_class<F1,F2> compose(F1 f1,F2 f2)
{
return {f1,f2};
}
template<typename F1,typename F2>
struct compose_all_class
{
F1 f1;
F2 f2;
compose_all_class(const F1& f1,const F2& f2):f1(f1),f2(f2){}
template<typename... Args>
auto operator()(Args&&... args)
->decltype(std::declval<F2>()(std::declval<F1>()(
std::forward<Args>(args))...))
{
return f2(f1(std::forward<Args>(args))...);
}
};
template<typename F1,typename F2>
compose_all_class<F1,F2> compose_all(F1 f1,F2 f2)
{
return {f1,f2};
}
using std::is_default_constructible;
using std::is_copy_constructible;
template<typename T>
using is_not_copy_constructible=std::integral_constant<
bool,
!std::is_copy_constructible<T>::value
>;
template<typename T>
using is_constructible_from_int=std::is_constructible<T,int>;
using std::is_copy_assignable;
template<typename T>
using is_not_copy_assignable=std::integral_constant<
bool,
!std::is_copy_assignable<T>::value
>;
template<typename T>
using is_equality_comparable=std::integral_constant<
bool,
boost::has_equal_to<T,T>::value
>;
template<typename T>
using is_not_equality_comparable=std::integral_constant<
bool,
!is_equality_comparable<T>::value
>;
template<
typename T,
typename std::enable_if<is_not_copy_constructible<T>::value>::type* =nullptr
>
typename std::remove_reference<T>::type&& constref_if_copy_constructible(T&& x)
{
return std::move(x);
}
template<
typename T,
typename std::enable_if<is_copy_constructible<T>::value>::type* =nullptr
>
const T& constref_if_copy_constructible(T&& x)
{
return x;
}
template<template<typename> class... Traits>
struct constraints;
template<>
struct constraints<>
{
template<typename T>
struct apply:std::true_type{};
};
template<
template <typename> class Trait,
template <typename> class... Traits
>
struct constraints<Trait,Traits...>
{
template<typename T>
struct apply:std::integral_constant<
bool,
Trait<T>::value&&constraints<Traits...>::template apply<T>::value
>{};
};
template<typename... Ts>struct type_list{};
template<
typename Constraints,template <typename...> class Template,
typename TypeList,
typename... Ts
>
struct instantiate_with_class;
template<
typename Constraints,template <typename...> class Template,
typename... Us
>
struct instantiate_with_class<Constraints,Template,type_list<Us...>>
{using type=Template<Us...>;};
template<
typename Constraints,template <typename...> class Template,
typename... Us,
typename T,typename... Ts
>
struct instantiate_with_class<
Constraints,Template,type_list<Us...>,T,Ts...
>:instantiate_with_class<
Constraints,Template,
typename std::conditional<
Constraints::template apply<T>::value,
type_list<Us...,T>,
type_list<Us...>
>::type,
Ts...
>{};
template<
typename Constraints,template <typename...> class Template,
typename... Ts
>
using instantiate_with=typename instantiate_with_class<
Constraints,Template,type_list<>,Ts...
>::type;
template<
template <typename...> class Template,typename... Ts
>
using only_eq_comparable=instantiate_with<
constraints<is_equality_comparable>,
Template, Ts...
>;
template<typename T> struct identity{using type=T;};
template<typename Constraints,typename... Ts>
struct first_of_class{};
template<typename Constraints,typename T,typename... Ts>
struct first_of_class<Constraints,T,Ts...>:std::conditional<
Constraints::template apply<T>::value,
identity<T>,
first_of_class<Constraints,Ts...>
>::type{};
template<typename Constraints,typename... Ts>
using first_of=typename first_of_class<Constraints,Ts...>::type;
template<
typename Constraints,typename... Ts,
typename PolyCollection,typename ValueFactory
>
void fill(PolyCollection& p,ValueFactory& v,int n)
{
for(int i=0;i<n;++i){
do_(
(Constraints::template apply<Ts>::value?
(p.insert(v.template make<Ts>()),0):0)...);
}
}
template<typename PolyCollection>
bool is_first(
const PolyCollection& p,typename PolyCollection::const_iterator it)
{
return it==p.begin();
}
template<typename PolyCollection,typename Iterator>
bool is_first(const PolyCollection& p,const std::type_info& info,Iterator it)
{
return &*it==&*p.begin(info);
}
template<typename PolyCollection,typename Iterator>
bool is_last(const PolyCollection& p,const std::type_info& info,Iterator it)
{
return &*it==&*(p.end(info)-1);
}
template<typename T,typename PolyCollection,typename Iterator>
bool is_first(const PolyCollection& p,Iterator it)
{
return &*it==&*p.template begin<T>();
}
template<typename T,typename PolyCollection,typename Iterator>
bool is_last(const PolyCollection& p,Iterator it)
{
return &*it==&*(p.template end<T>()-1);
}
template<typename Iterator>
struct external_iterator_class:
public boost::iterator_adaptor<external_iterator_class<Iterator>,Iterator>
{
external_iterator_class(const Iterator& it):
external_iterator_class::iterator_adaptor_{it}{}
};
template<typename Iterator>
external_iterator_class<Iterator> external_iterator(Iterator it)
{
return it;
}
template<typename Iterator>
struct unwrap_iterator_class:public boost::iterator_adaptor<
unwrap_iterator_class<Iterator>,
Iterator,
typename std::iterator_traits<Iterator>::value_type::type
>
{
unwrap_iterator_class(const Iterator& it):
unwrap_iterator_class::iterator_adaptor_{it}{}
};
template<typename Iterator>
unwrap_iterator_class<Iterator> unwrap_iterator(Iterator it)
{
return it;
}
struct auto_increment
{
template<typename T>
T make(){return T(n++);}
int n=0;
};
struct jammed_auto_increment
{
template<typename T>
T make(){return T(n++/10);}
int n=0;
};
template<typename T>
struct rooted_allocator:std::allocator<T>
{
using propagate_on_container_copy_assignment=std::false_type;
using propagate_on_container_move_assignment=std::true_type;
using propagate_on_container_swap=std::false_type;
template<typename U>
struct rebind{using other=rooted_allocator<U>;};
rooted_allocator()=default;
explicit rooted_allocator(int):root{this}{}
template<typename U>
rooted_allocator(const rooted_allocator<U>& x):root{x.root}{}
const void* root;
};
template<typename PolyCollection,template<typename> class Allocator>
struct realloc_poly_collection_class;
template<typename PolyCollection,template<typename> class Allocator>
using realloc_poly_collection=
typename realloc_poly_collection_class<PolyCollection,Allocator>::type;
template<
template<typename,typename> class PolyCollection,
typename T,typename OriginalAllocator,
template<typename> class Allocator
>
struct realloc_poly_collection_class<
PolyCollection<T,OriginalAllocator>,Allocator
>
{
using value_type=typename PolyCollection<T,OriginalAllocator>::value_type;
using type=PolyCollection<T,Allocator<value_type>>;
};
template<std::size_t N>
struct layout_data
{
std::array<const void*,N> datas;
std::array<std::size_t,N> sizes;
bool operator==(const layout_data& x)const
{
return datas==x.datas&&sizes==x.sizes;
}
};
template<typename... Types,typename PolyCollection>
layout_data<sizeof...(Types)> get_layout_data(const PolyCollection& p)
{
return{
{{(p.template is_registered<Types>()?
&*p.template begin<Types>():nullptr)...}},
{{(p.template is_registered<Types>()?
p.template size<Types>():0)...}}
};
}
} /* namespace test_utilities */
#endif