diff options
Diffstat (limited to 'src/boost/libs/multi_index')
107 files changed, 10041 insertions, 0 deletions
diff --git a/src/boost/libs/multi_index/README.md b/src/boost/libs/multi_index/README.md new file mode 100644 index 000000000..93a9f2faa --- /dev/null +++ b/src/boost/libs/multi_index/README.md @@ -0,0 +1,10 @@ +# Boost Multi-index Containers Library + +Branch | Travis | AppVeyor | Regression tests +---------|--------|----------|----------------- +develop | [![Build Status](https://travis-ci.com/boostorg/multi_index.svg?branch=develop)](https://travis-ci.com/boostorg/multi_index) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/boostorg/multi_index?branch=develop&svg=true)](https://ci.appveyor.com/project/joaquintides/multi-index) | [![Test Results](./test_results.svg)](https://www.boost.org/development/tests/develop/developer/multi_index.html) +master | [![Build Status](https://travis-ci.com/boostorg/multi_index.svg?branch=master)](https://travis-ci.com/boostorg/multi_index) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/boostorg/multi_index?branch=master&svg=true)](https://ci.appveyor.com/project/joaquintides/multi-index) | [![Test Results](./test_results.svg)](https://www.boost.org/development/tests/master/developer/multi_index.html) + +[Boost.MultiIndex](http://boost.org/libs/multi_index) provides a class template +named `multi_index_container` which enables the construction of containers +maintaining one or more indices with different sorting and access semantics. diff --git a/src/boost/libs/multi_index/example/Jamfile.v2 b/src/boost/libs/multi_index/example/Jamfile.v2 new file mode 100644 index 000000000..a4dc9c318 --- /dev/null +++ b/src/boost/libs/multi_index/example/Jamfile.v2 @@ -0,0 +1,69 @@ +# Boost.MultiIndex examples Jamfile +# +# Copyright 2003-2007 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) +# +# See http://www.boost.org/libs/multi_index for library home page. + +exe basic + : basic.cpp + : <include>$(BOOST_ROOT) + ; + +exe bimap + : bimap.cpp + : <include>$(BOOST_ROOT) + ; + +exe complex_structs + : complex_structs.cpp + : <include>$(BOOST_ROOT) + ; + +exe composite_keys + : composite_keys.cpp + : <include>$(BOOST_ROOT) + ; + +exe fun_key + : fun_key.cpp + : <include>$(BOOST_ROOT) + ; + +exe hashed + : hashed.cpp + : <include>$(BOOST_ROOT) + ; + +exe ip_allocator + : ip_allocator.cpp + : <include>$(BOOST_ROOT) <threading>multi + ; + +exe non_default_ctor + : non_default_ctor.cpp + : <include>$(BOOST_ROOT) + ; + +exe random_access + : random_access.cpp + : <include>$(BOOST_ROOT) + ; + +exe rearrange + : rearrange.cpp + : <include>$(BOOST_ROOT) + ; + +exe sequenced + : sequenced.cpp + : <include>$(BOOST_ROOT) + ; + +exe serialization + : serialization.cpp + /boost/serialization//boost_serialization + : <include>$(BOOST_ROOT) + ; diff --git a/src/boost/libs/multi_index/example/basic.cpp b/src/boost/libs/multi_index/example/basic.cpp new file mode 100644 index 000000000..f7c46ced0 --- /dev/null +++ b/src/boost/libs/multi_index/example/basic.cpp @@ -0,0 +1,119 @@ +/* Boost.MultiIndex basic example. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <algorithm> +#include <iostream> +#include <iterator> +#include <string> + +using boost::multi_index_container; +using namespace boost::multi_index; + +/* an employee record holds its ID, name and age */ + +struct employee +{ + int id; + std::string name; + int age; + + employee(int id_,std::string name_,int age_):id(id_),name(name_),age(age_){} + + friend std::ostream& operator<<(std::ostream& os,const employee& e) + { + os<<e.id<<" "<<e.name<<" "<<e.age<<std::endl; + return os; + } +}; + +/* tags for accessing the corresponding indices of employee_set */ + +struct id{}; +struct name{}; +struct age{}; + +/* see Compiler specifics: Use of member_offset for info on + * BOOST_MULTI_INDEX_MEMBER + */ + +/* Define a multi_index_container of employees with following indices: + * - a unique index sorted by employee::int, + * - a non-unique index sorted by employee::name, + * - a non-unique index sorted by employee::age. + */ + +typedef multi_index_container< + employee, + indexed_by< + ordered_unique< + tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)>, + ordered_non_unique< + tag<name>,BOOST_MULTI_INDEX_MEMBER(employee,std::string,name)>, + ordered_non_unique< + tag<age>, BOOST_MULTI_INDEX_MEMBER(employee,int,age)> > +> employee_set; + +template<typename Tag,typename MultiIndexContainer> +void print_out_by(const MultiIndexContainer& s) +{ + /* obtain a reference to the index tagged by Tag */ + + const typename boost::multi_index::index<MultiIndexContainer,Tag>::type& i= + get<Tag>(s); + + typedef typename MultiIndexContainer::value_type value_type; + + /* dump the elements of the index to cout */ + + std::copy(i.begin(),i.end(),std::ostream_iterator<value_type>(std::cout)); +} + + +int main() +{ + employee_set es; + + es.insert(employee(0,"Joe",31)); + es.insert(employee(1,"Robert",27)); + es.insert(employee(2,"John",40)); + + /* next insertion will fail, as there is an employee with + * the same ID + */ + + es.insert(employee(2,"Aristotle",2387)); + + es.insert(employee(3,"Albert",20)); + es.insert(employee(4,"John",57)); + + /* list the employees sorted by ID, name and age */ + + std::cout<<"by ID"<<std::endl; + print_out_by<id>(es); + std::cout<<std::endl; + + std::cout<<"by name"<<std::endl; + print_out_by<name>(es); + std::cout<<std::endl; + + std::cout<<"by age"<<std::endl; + print_out_by<age>(es); + std::cout<<std::endl; + + return 0; +} diff --git a/src/boost/libs/multi_index/example/bimap.cpp b/src/boost/libs/multi_index/example/bimap.cpp new file mode 100644 index 000000000..aac99d06c --- /dev/null +++ b/src/boost/libs/multi_index/example/bimap.cpp @@ -0,0 +1,149 @@ +/* Boost.MultiIndex example of a bidirectional map. + * + * Copyright 2003-2009 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <iostream> +#include <string> + +using boost::multi_index_container; +using namespace boost::multi_index; + +/* tags for accessing both sides of a bidirectional map */ + +struct from{}; +struct to{}; + +/* The class template bidirectional_map wraps the specification + * of a bidirectional map based on multi_index_container. + */ + +template<typename FromType,typename ToType> +struct bidirectional_map +{ + struct value_type + { + value_type(const FromType& first_,const ToType& second_): + first(first_),second(second_) + {} + + FromType first; + ToType second; + }; + +#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\ + defined(BOOST_MSVC)&&(BOOST_MSVC<1300) ||\ + defined(BOOST_INTEL_CXX_VERSION)&&defined(_MSC_VER)&&\ + (BOOST_INTEL_CXX_VERSION<=700) + +/* see Compiler specifics: Use of member_offset for info on member<> and + * member_offset<> + */ + + BOOST_STATIC_CONSTANT(unsigned,from_offset=offsetof(value_type,first)); + BOOST_STATIC_CONSTANT(unsigned,to_offset =offsetof(value_type,second)); + + typedef multi_index_container< + value_type, + indexed_by< + ordered_unique< + tag<from>,member_offset<value_type,FromType,from_offset> >, + ordered_unique< + tag<to>, member_offset<value_type,ToType,to_offset> > + > + > type; + +#else + + /* A bidirectional map can be simulated as a multi_index_container + * of pairs of (FromType,ToType) with two unique indices, one + * for each member of the pair. + */ + + typedef multi_index_container< + value_type, + indexed_by< + ordered_unique< + tag<from>,member<value_type,FromType,&value_type::first> >, + ordered_unique< + tag<to>, member<value_type,ToType,&value_type::second> > + > + > type; + +#endif +}; + +/* a dictionary is a bidirectional map from strings to strings */ + +typedef bidirectional_map<std::string,std::string>::type dictionary; + +int main() +{ + dictionary d; + + /* Fill up our microdictionary. first members Spanish, second members + * English. + */ + + d.insert(dictionary::value_type("hola","hello")); + d.insert(dictionary::value_type("adios","goodbye")); + d.insert(dictionary::value_type("rosa","rose")); + d.insert(dictionary::value_type("mesa","table")); + + + std::cout<<"enter a word"<<std::endl; + std::string word; + std::getline(std::cin,word); + +#if defined(BOOST_NO_MEMBER_TEMPLATES) /* use global get<> and family instead */ + + dictionary::iterator it=get<from>(d).find(word); + if(it!=d.end()){ + std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl; + } + else{ + nth_index<dictionary,1>::type::iterator it2=get<1>(d).find(word); + if(it2!=get<1>(d).end()){ + std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl; + } + else std::cout<<"No such word in the dictionary"<<std::endl; + } + +#else + + /* search the queried word on the from index (Spanish) */ + + dictionary::iterator it=d.get<from>().find(word); + if(it!=d.end()){ /* found */ + + /* the second part of the element is the equivalent in English */ + + std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl; + } + else{ + /* word not found in Spanish, try our luck in English */ + + dictionary::index<to>::type::iterator it2=d.get<to>().find(word); + if(it2!=d.get<to>().end()){ + std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl; + } + else std::cout<<"No such word in the dictionary"<<std::endl; + } + +#endif + + return 0; +} diff --git a/src/boost/libs/multi_index/example/complex_structs.cpp b/src/boost/libs/multi_index/example/complex_structs.cpp new file mode 100644 index 000000000..70eb78bcd --- /dev/null +++ b/src/boost/libs/multi_index/example/complex_structs.cpp @@ -0,0 +1,315 @@ +/* Boost.MultiIndex example: complex searches and foreign keys. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/tuple/tuple.hpp> +#include <iostream> +#include <string> + +using boost::multi_index_container; +using namespace boost::multi_index; + +/* This small utility that cascades two key extractors will be + * used througout the example. + */ + +template<class KeyExtractor1,class KeyExtractor2> +struct key_from_key +{ +public: + typedef typename KeyExtractor1::result_type result_type; + + key_from_key( + const KeyExtractor1& key1_=KeyExtractor1(), + const KeyExtractor2& key2_=KeyExtractor2()): + key1(key1_),key2(key2_) + {} + + template<typename Arg> + result_type operator()(Arg& arg)const + { + return key1(key2(arg)); + } + +private: + KeyExtractor1 key1; + KeyExtractor2 key2; +}; + +/* tags for accessing several indices defined below */ + +struct model{}; +struct manufacturer{}; +struct price{}; + +/* a manufacturer struct just holds the name of the manufacturer */ + +struct car_manufacturer +{ + std::string name; + + car_manufacturer(const std::string& name_):name(name_){} +}; + +/* car_model holds the model of car, its price and a pointer to the + * manufacturer. The pointer thing eliminates duplication of the same + * data among cars of the same manufacturer. + */ + +struct car_model +{ + std::string model; + const car_manufacturer* manufacturer; + int price; + + car_model( + const std::string& model_,const car_manufacturer* manufacturer_,int price_): + model(model_),manufacturer(manufacturer_),price(price_) + {} + + friend std::ostream& operator<<(std::ostream& os,const car_model& c) + { + os<<c.manufacturer->name<<" "<<c.model<<" $"<<c.price<<std::endl; + return os; + } +}; + +/* see Compiler specifics: Use of member_offset for info on + * BOOST_MULTI_INDEX_MEMBER + */ + +/* Car manufacturers are stored in a multi_index_container with one single + * index on the name member. This is functionally equivalent to an std::set, + * though in this latter case we woud have to define a non-default comparison + * predicate (with multi_index_container, member<> does the work for us.) + */ + +typedef multi_index_container< + car_manufacturer, + indexed_by< + ordered_unique< + BOOST_MULTI_INDEX_MEMBER(car_manufacturer,std::string,name) + > + > +> car_manufacturer_table; + +/* Define a multi_index_container of car_models with following indices: + * - a unique index sorted by car_model::model, + * - a non-unique index sorted by car_model::manufacturer; note the + * non-standard manufacturer_extractor used. + * - a non-unique index sorted by car_model::price. + */ + +typedef multi_index_container< + car_model, + indexed_by< + ordered_unique< + tag<model>,BOOST_MULTI_INDEX_MEMBER(car_model,std::string,model) + >, + ordered_non_unique< + tag<manufacturer>, + key_from_key< + BOOST_MULTI_INDEX_MEMBER(car_manufacturer,const std::string,name), + BOOST_MULTI_INDEX_MEMBER( + car_model,const car_manufacturer *,manufacturer) + > + >, + ordered_non_unique< + tag<price>,BOOST_MULTI_INDEX_MEMBER(car_model,int,price) + > + > +> car_table; + +/* We call a *view* to a multi_index_container storing pointers instead of + * actual objects. These views are used in the complex search performed + * in the program. Resorting to multi_index of pointers eliminates + * unnecessary copying of objects, and provides us with an opportunity + * to show how BOOST_MULTI_INDEX_MEMBER can be used with pointer + * type elements. + * car_table_price_view indexes (pointers to) car_models by price. + */ + +typedef multi_index_container< + const car_model*, + indexed_by< + ordered_non_unique<BOOST_MULTI_INDEX_MEMBER(car_model,const int,price)> + > +> car_table_price_view; + +/* car_table_manufacturer_view indexes (pointers to) car_models by + * manufacturer + */ + +typedef multi_index_container< + const car_model*, + indexed_by< + ordered_non_unique< + key_from_key< + BOOST_MULTI_INDEX_MEMBER(car_manufacturer,const std::string,name), + BOOST_MULTI_INDEX_MEMBER( + car_model,const car_manufacturer * const,manufacturer) + > + > + > +> car_table_manufacturer_view; + +int main() +{ + car_manufacturer_table cmt; + + /* Fill the car_manufacturer table and keep pointers to the + * elements inserted. + */ + + const car_manufacturer * cadillac= + &*(cmt.insert(car_manufacturer("Cadillac")).first); + const car_manufacturer * ford = + &*(cmt.insert(car_manufacturer("Ford")).first); + const car_manufacturer * bmw = + &*(cmt.insert(car_manufacturer("BMW")).first); + const car_manufacturer * audi = + &*(cmt.insert(car_manufacturer("Audi")).first); + + car_table ct; + + /* Fill the car_model_table. We use the previously initialized + * pointers to the elements of cmt. + */ + + ct.insert(car_model("XLR",cadillac,76200)); + ct.insert(car_model("SRX",cadillac,38690)); + ct.insert(car_model("CTS",cadillac,30695)); + ct.insert(car_model("Escalade",cadillac,54770)); + ct.insert(car_model("ESV",cadillac,57195)); + ct.insert(car_model("EXT",cadillac,52045)); + ct.insert(car_model("Deville",cadillac,45195)); + ct.insert(car_model("Seville",cadillac,46330)); + + ct.insert(car_model("ZX2",ford,15355)); + ct.insert(car_model("Thunderbird",ford,43995)); + ct.insert(car_model("Windstar",ford,35510)); + ct.insert(car_model("Focus",ford,19630)); + ct.insert(car_model("Taurus",ford,24290)); + ct.insert(car_model("Mustang",ford,39900)); + ct.insert(car_model("Crown Victoria",ford,30370)); + + ct.insert(car_model("325i",bmw,27800)); + ct.insert(car_model("545i",bmw,54300)); + ct.insert(car_model("745i",bmw,68500)); + ct.insert(car_model("M3 coupe",bmw,46500)); + ct.insert(car_model("Z4 roadster 3.0i",bmw,40250)); + ct.insert(car_model("X5 4.4i",bmw,49950)); + + ct.insert(car_model("A4 1.8T",audi,25940)); + ct.insert(car_model("TT Coupe",audi,33940)); + ct.insert(car_model("A6 3.0",audi,36640)); + ct.insert(car_model("Allroad quattro 2.7T",audi,40640)); + ct.insert(car_model("A8 L",audi,69190)); + + std::cout<<"enter a car manufacturer"<<std::endl; + std::string cm; + std::getline(std::cin,cm); + + /* check for manufacturer */ + + car_manufacturer_table::iterator icm=cmt.find(cm); + + if(icm==cmt.end()){ + std::cout<<"no such manufacturer in the table"<<std::endl; + return 0; + } + + std::cout<<"enter a minimum price"<<std::endl; + int min_price; + std::cin>>min_price; + std::cout<<"enter a maximum price"<<std::endl; + int max_price; + std::cin>>max_price; + + { + /* method 1 */ + + /* find all the cars for the manufacturer given */ + + boost::multi_index::index<car_table,manufacturer>::type::iterator ic0,ic1; + boost::tuples::tie(ic0,ic1)=get<manufacturer>(ct).equal_range(cm); + + /* construct a view (indexed by price) with these */ + + car_table_price_view ctpv; + while(ic0!=ic1){ + ctpv.insert(&*ic0); + ++ic0; + } + + /* select the cars in the range given */ + + car_table_price_view::iterator ictpv0=ctpv.lower_bound(min_price); + car_table_price_view::iterator ictpv1=ctpv.upper_bound(max_price); + if(ictpv0==ictpv1){ + std::cout<<"no cars in the range given"<<std::endl; + return 0; + } + + /* list them */ + + std::cout<<"listing by method 1"<<std::endl; + while(ictpv0!=ictpv1){ + std::cout<<**ictpv0; + ++ictpv0; + } + std::cout<<std::endl; + } + + { + /* method 2 will give the same results */ + + /* find the cars in the range given */ + + boost::multi_index::index<car_table,price>::type::iterator ic0,ic1; + ic0=get<price>(ct).lower_bound(min_price); + ic1=get<price>(ct).upper_bound(max_price); + + /* construct a view with these */ + + car_table_manufacturer_view ctmv; + while(ic0!=ic1){ + ctmv.insert(&*ic0); + ++ic0; + } + + /* select the cars with given manufacturer */ + + car_table_manufacturer_view::iterator ictmv0,ictmv1; + boost::tuples::tie(ictmv0,ictmv1)=ctmv.equal_range(cm); + if(ictmv0==ictmv1){ + std::cout<<"no cars in the range given"<<std::endl; + return 0; + } + + /* list them */ + + std::cout<<"listing by method 2"<<std::endl; + while(ictmv0!=ictmv1){ + std::cout<<**ictmv0; + ++ictmv0; + } + std::cout<<std::endl; + } + + return 0; +} diff --git a/src/boost/libs/multi_index/example/composite_keys.cpp b/src/boost/libs/multi_index/example/composite_keys.cpp new file mode 100644 index 000000000..e9da2affa --- /dev/null +++ b/src/boost/libs/multi_index/example/composite_keys.cpp @@ -0,0 +1,285 @@ +/* Boost.MultiIndex example of composite keys. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/call_traits.hpp> +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/composite_key.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/next_prior.hpp> +#include <boost/tokenizer.hpp> +#include <functional> +#include <iostream> +#include <iterator> +#include <map> +#include <string> + +using namespace boost::multi_index; + +/* A file record maintains some info on name and size as well + * as a pointer to the directory it belongs (null meaning the root + * directory.) + */ + +struct file_entry +{ + file_entry( + std::string name_,unsigned size_,bool is_dir_,const file_entry* dir_): + name(name_),size(size_),is_dir(is_dir_),dir(dir_) + {} + + std::string name; + unsigned size; + bool is_dir; + const file_entry* dir; + + friend std::ostream& operator<<(std::ostream& os,const file_entry& f) + { + os<<f.name<<"\t"<<f.size; + if(f.is_dir)os<<"\t <dir>"; + return os; + } +}; + +/* A file system is just a multi_index_container of entries with indices on + * file and size. These indices are firstly ordered by directory, as commands + * work on a current directory basis. Composite keys are just fine to model + * this. + * NB: The use of derivation here instead of simple typedef is explained in + * Compiler specifics: type hiding. + */ + +struct name_key:composite_key< + file_entry, + BOOST_MULTI_INDEX_MEMBER(file_entry,const file_entry*,dir), + BOOST_MULTI_INDEX_MEMBER(file_entry,std::string,name) +>{}; + +struct size_key:composite_key< + file_entry, + BOOST_MULTI_INDEX_MEMBER(file_entry,const file_entry* const,dir), + BOOST_MULTI_INDEX_MEMBER(file_entry,unsigned,size) +>{}; + +/* see Compiler specifics: composite_key in compilers without partial + * template specialization, for info on composite_key_result_less + */ + +typedef multi_index_container< + file_entry, + indexed_by< + /* primary index sorted by name (inside the same directory) */ + ordered_unique<name_key>, + /* secondary index sorted by size (inside the same directory) */ + ordered_non_unique<size_key> + > +> file_system; + +/* typedef's of the two indices of file_system */ + +typedef nth_index<file_system,0>::type file_system_by_name; +typedef nth_index<file_system,1>::type file_system_by_size; + +/* We build a rudimentary file system simulation out of some global + * info and a map of commands provided to the user. + */ + +static file_system fs; /* the one and only file system */ +static file_system_by_name& fs_by_name=fs; /* name index to fs */ +static file_system_by_size& fs_by_size=get<1>(fs); /* size index to fs */ +static const file_entry* current_dir=0; /* root directory */ + +/* command framework */ + +/* A command provides an execute memfun fed with the corresponding params + * (first param is stripped off as it serves to identify the command + * currently being used.) + */ + +typedef boost::tokenizer<boost::char_separator<char> > command_tokenizer; + +class command +{ +public: + virtual ~command(){} + virtual void execute( + command_tokenizer::iterator tok1,command_tokenizer::iterator tok2)=0; +}; + +/* available commands */ + +/* cd: syntax cd [.|..|<directory>] */ + +class command_cd:public command +{ +public: + virtual void execute( + command_tokenizer::iterator tok1,command_tokenizer::iterator tok2) + { + if(tok1==tok2)return; + std::string dir=*tok1++; + + if(dir==".")return; + if(dir==".."){ + if(current_dir)current_dir=current_dir->dir; + return; + } + + file_system_by_name::iterator it=fs.find( + boost::make_tuple(current_dir,dir)); + if(it==fs.end()){ + std::cout<<"non-existent directory"<<std::endl; + return; + } + if(!it->is_dir){ + std::cout<<dir<<" is not a directory"<<std::endl; + return; + } + current_dir=&*it; + } +}; +static command_cd cd; + +/* ls: syntax ls [-s] */ + +class command_ls:public command +{ +public: + virtual void execute( + command_tokenizer::iterator tok1,command_tokenizer::iterator tok2) + { + std::string option; + if(tok1!=tok2)option=*tok1++; + + if(!option.empty()){ + if(option!="-s"){ + std::cout<<"incorrect parameter"<<std::endl; + return; + } + + /* list by size */ + + file_system_by_size::iterator it0,it1; + boost::tie(it0,it1)=fs_by_size.equal_range( + boost::make_tuple(current_dir)); + std::copy(it0,it1,std::ostream_iterator<file_entry>(std::cout,"\n")); + + return; + } + + /* list by name */ + + file_system_by_name::iterator it0,it1; + boost::tie(it0,it1)=fs.equal_range(boost::make_tuple(current_dir)); + std::copy(it0,it1,std::ostream_iterator<file_entry>(std::cout,"\n")); + } +}; +static command_ls ls; + +/* mkdir: syntax mkdir <directory> */ + +class command_mkdir:public command +{ +public: + virtual void execute( + command_tokenizer::iterator tok1,command_tokenizer::iterator tok2) + { + std::string dir; + if(tok1!=tok2)dir=*tok1++; + + if(dir.empty()){ + std::cout<<"missing parameter"<<std::endl; + return; + } + + if(dir=="."||dir==".."){ + std::cout<<"incorrect parameter"<<std::endl; + return; + } + + if(!fs.insert(file_entry(dir,0,true,current_dir)).second){ + std::cout<<"directory already exists"<<std::endl; + return; + } + } +}; +static command_mkdir mkdir; + +/* table of commands, a map from command names to class command pointers */ + +typedef std::map<std::string,command*> command_table; +static command_table cmt; + +int main() +{ + /* fill the file system with some data */ + + file_system::iterator it0,it1; + + fs.insert(file_entry("usr.cfg",240,false,0)); + fs.insert(file_entry("memo.txt",2430,false,0)); + it0=fs.insert(file_entry("dev",0,true,0)).first; + fs.insert(file_entry("tty0",128,false,&*it0)); + fs.insert(file_entry("tty1",128,false,&*it0)); + it0=fs.insert(file_entry("usr",0,true,0)).first; + it1=fs.insert(file_entry("bin",0,true,&*it0)).first; + fs.insert(file_entry("bjam",172032,false,&*it1)); + it0=fs.insert(file_entry("home",0,true,0)).first; + it1=fs.insert(file_entry("andy",0,true,&*it0)).first; + fs.insert(file_entry("logo.jpg",5345,false,&*it1)).first; + fs.insert(file_entry("foo.cpp",890,false,&*it1)).first; + fs.insert(file_entry("foo.hpp",93,false,&*it1)).first; + fs.insert(file_entry("foo.html",750,false,&*it1)).first; + fs.insert(file_entry("a.obj",12302,false,&*it1)).first; + fs.insert(file_entry(".bash_history",8780,false,&*it1)).first; + it1=fs.insert(file_entry("rachel",0,true,&*it0)).first; + fs.insert(file_entry("test.py",650,false,&*it1)).first; + fs.insert(file_entry("todo.txt",241,false,&*it1)).first; + fs.insert(file_entry(".bash_history",9510,false,&*it1)).first; + + /* fill the command table */ + + cmt["cd"] =&cd; + cmt["ls"] =&ls; + cmt["mkdir"]=&mkdir; + + /* main looop */ + + for(;;){ + /* print out the current directory and the prompt symbol */ + + if(current_dir)std::cout<<current_dir->name; + std::cout<<">"; + + /* get an input line from the user: if empty, exit the program */ + + std::string com; + std::getline(std::cin,com); + command_tokenizer tok(com,boost::char_separator<char>(" \t\n")); + if(tok.begin()==tok.end())break; /* null command, exit */ + + /* select the corresponding command and execute it */ + + command_table::iterator it=cmt.find(*tok.begin()); + if(it==cmt.end()){ + std::cout<<"invalid command"<<std::endl; + continue; + } + + it->second->execute(boost::next(tok.begin()),tok.end()); + } + + return 0; +} diff --git a/src/boost/libs/multi_index/example/fun_key.cpp b/src/boost/libs/multi_index/example/fun_key.cpp new file mode 100644 index 000000000..769d7bf6c --- /dev/null +++ b/src/boost/libs/multi_index/example/fun_key.cpp @@ -0,0 +1,100 @@ +/* Boost.MultiIndex example of functions used as key extractors. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/global_fun.hpp> +#include <boost/multi_index/mem_fun.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <iostream> +#include <string> + +using namespace boost::multi_index; + +/* A name record consists of the given name (e.g. "Charlie") + * and the family name (e.g. "Brown"). The full name, calculated + * by name_record::name() is laid out in the "phonebook order" + * family name + given_name. + */ + +struct name_record +{ + name_record(std::string given_name_,std::string family_name_): + given_name(given_name_),family_name(family_name_) + {} + + std::string name()const + { + std::string str=family_name; + str+=" "; + str+=given_name; + return str; + } + +private: + std::string given_name; + std::string family_name; +}; + +std::string::size_type name_record_length(const name_record& r) +{ + return r.name().size(); +} + +/* multi_index_container with indices based on name_record::name() + * and name_record_length(). + * See Compiler specifics: Use of const_mem_fun_explicit and + * mem_fun_explicit for info on BOOST_MULTI_INDEX_CONST_MEM_FUN. + */ + +typedef multi_index_container< + name_record, + indexed_by< + ordered_unique< + BOOST_MULTI_INDEX_CONST_MEM_FUN(name_record,std::string,name) + >, + ordered_non_unique< + global_fun<const name_record&,std::string::size_type,name_record_length> + > + > +> name_record_set; + +int main() +{ + name_record_set ns; + + ns.insert(name_record("Joe","Smith")); + ns.insert(name_record("Robert","Nightingale")); + ns.insert(name_record("Robert","Brown")); + ns.insert(name_record("Marc","Tuxedo")); + + /* list the names in ns in phonebook order */ + + std::cout<<"Phonenook order\n" + <<"---------------"<<std::endl; + for(name_record_set::iterator it=ns.begin();it!=ns.end();++it){ + std::cout<<it->name()<<std::endl; + } + + /* list the names in ns according to their length*/ + + std::cout<<"\nLength order\n" + << "------------"<<std::endl; + for(nth_index<name_record_set,1>::type::iterator it1=get<1>(ns).begin(); + it1!=get<1>(ns).end();++it1){ + std::cout<<it1->name()<<std::endl; + } + + return 0; +} diff --git a/src/boost/libs/multi_index/example/hashed.cpp b/src/boost/libs/multi_index/example/hashed.cpp new file mode 100644 index 000000000..98228ea25 --- /dev/null +++ b/src/boost/libs/multi_index/example/hashed.cpp @@ -0,0 +1,124 @@ +/* Boost.MultiIndex example of use of hashed indices. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/tokenizer.hpp> +#include <iomanip> +#include <iostream> +#include <string> + +using boost::multi_index_container; +using namespace boost::multi_index; + +/* word_counter keeps the ocurrences of words inserted. A hashed + * index allows for fast checking of preexisting entries. + */ + +struct word_counter_entry +{ + std::string word; + unsigned int occurrences; + + word_counter_entry(std::string word_):word(word_),occurrences(0){} +}; + +/* see Compiler specifics: Use of member_offset for info on + * BOOST_MULTI_INDEX_MEMBER + */ + +typedef multi_index_container< + word_counter_entry, + indexed_by< + ordered_non_unique< + BOOST_MULTI_INDEX_MEMBER(word_counter_entry,unsigned int,occurrences), + std::greater<unsigned int> /* sorted beginning with most frequent */ + >, + hashed_unique< + BOOST_MULTI_INDEX_MEMBER(word_counter_entry,std::string,word) + > + > +> word_counter; + +/* utilities */ + +template<typename T> +struct increment +{ + void operator()(T& x)const{++x;} +}; + +typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer; + +int main() +{ + /* boostinspect:noascii */ + + std::string text= + "En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha " + "mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga " + "antigua, rocín flaco y galgo corredor. Una olla de algo más vaca que " + "carnero, salpicón las más noches, duelos y quebrantos los sábados, " + "lantejas los viernes, algún palomino de añadidura los domingos, " + "consumían las tres partes de su hacienda. El resto della concluían sayo " + "de velarte, calzas de velludo para las fiestas, con sus pantuflos de lo " + "mesmo, y los días de entresemana se honraba con su vellorí de lo más " + "fino. Tenía en su casa una ama que pasaba de los cuarenta, y una " + "sobrina que no llegaba a los veinte, y un mozo de campo y plaza, que " + "así ensillaba el rocín como tomaba la podadera. Frisaba la edad de " + "nuestro hidalgo con los cincuenta años; era de complexión recia, seco " + "de carnes, enjuto de rostro, gran madrugador y amigo de la caza. " + "Quieren decir que tenía el sobrenombre de Quijada, o Quesada, que en " + "esto hay alguna diferencia en los autores que deste caso escriben; " + "aunque, por conjeturas verosímiles, se deja entender que se llamaba " + "Quejana. Pero esto importa poco a nuestro cuento; basta que en la " + "narración dél no se salga un punto de la verdad."; + + /* feed the text into the container */ + + word_counter wc; + text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-")); + unsigned int total_occurrences=0; + for(text_tokenizer::iterator it=tok.begin(),it_end=tok.end(); + it!=it_end;++it){ + /* Insert the word into the container. If duplicate, wit will point to + * the preexistent entry. + */ + + ++total_occurrences; + word_counter::iterator wit=wc.insert(*it).first; + + /* Increment occurrences. + * In a lambda-capable compiler, this can be written as: + * wc.modify_key(wit,++_1); + */ + + wc.modify_key(wit,increment<unsigned int>()); + } + + /* list words by frequency of appearance */ + + std::cout<<std::fixed<<std::setprecision(2); + for(word_counter::iterator wit=wc.begin(),wit_end=wc.end(); + wit!=wit_end;++wit){ + std::cout<<std::setw(11)<<wit->word<<": " + <<std::setw(5) <<100.0*wit->occurrences/total_occurrences<<"%" + <<std::endl; + } + + return 0; +} diff --git a/src/boost/libs/multi_index/example/ip_allocator.cpp b/src/boost/libs/multi_index/example/ip_allocator.cpp new file mode 100644 index 000000000..f2c6d677d --- /dev/null +++ b/src/boost/libs/multi_index/example/ip_allocator.cpp @@ -0,0 +1,293 @@ +/* Boost.MultiIndex example of use of Boost.Interprocess allocators. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <boost/interprocess/allocators/allocator.hpp> +#include <boost/interprocess/containers/string.hpp> +#include <boost/interprocess/managed_mapped_file.hpp> +#include <boost/interprocess/sync/named_mutex.hpp> +#include <boost/interprocess/sync/scoped_lock.hpp> +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/member.hpp> +#include <iostream> +#include <iterator> +#include <sstream> +#include <string> + +using boost::multi_index_container; +using namespace boost::multi_index; +namespace bip=boost::interprocess; + +/* shared_string is a string type placeable in shared memory, + * courtesy of Boost.Interprocess. + */ + +typedef bip::basic_string< + char,std::char_traits<char>, + bip::allocator<char,bip::managed_mapped_file::segment_manager> +> shared_string; + +/* Book record. All its members can be placed in shared memory, + * hence the structure itself can too. + */ + +struct book +{ + shared_string name; + shared_string author; + unsigned pages; + unsigned prize; + + book(const shared_string::allocator_type& al): + name(al),author(al),pages(0),prize(0) + {} + + friend std::ostream& operator<<(std::ostream& os,const book& b) + { + os<<b.author<<": \""<<b.name<<"\", $"<<b.prize<<", "<<b.pages<<" pages\n"; + return os; + } +}; + +/* partial_str_less allows for partial searches taking into account + * only the first n chars of the strings compared against. See + * Tutorial: Basics: Special lookup operations for more info on this + * type of comparison functors. + */ + +/* partial_string is a mere string holder used to differentiate from + * a plain string. + */ + +struct partial_string +{ + partial_string(const shared_string& str):str(str){} + shared_string str; +}; + +struct partial_str_less +{ + bool operator()(const shared_string& x,const shared_string& y)const + { + return x<y; + } + + bool operator()(const shared_string& x,const partial_string& y)const + { + return x.substr(0,y.str.size())<y.str; + } + + bool operator()(const partial_string& x,const shared_string& y)const + { + return x.str<y.substr(0,x.str.size()); + } +}; + +/* Define a multi_index_container of book records with indices on + * author, name and prize. The index on names allows for partial + * searches. This container can be placed in shared memory because: + * * book can be placed in shared memory. + * * We are using a Boost.Interprocess specific allocator. + */ + +/* see Compiler specifics: Use of member_offset for info on + * BOOST_MULTI_INDEX_MEMBER + */ + +typedef multi_index_container< + book, + indexed_by< + ordered_non_unique< + BOOST_MULTI_INDEX_MEMBER(book,shared_string,author) + >, + ordered_non_unique< + BOOST_MULTI_INDEX_MEMBER(book,shared_string,name), + partial_str_less + >, + ordered_non_unique< + BOOST_MULTI_INDEX_MEMBER(book,unsigned,prize) + > + >, + bip::allocator<book,bip::managed_mapped_file::segment_manager> +> book_container; + +/* A small utility to get data entered via std::cin */ + +template<typename T> +void enter(const char* msg,T& t) +{ + std::cout<<msg; + std::string str; + std::getline(std::cin,str); + std::istringstream iss(str); + iss>>t; +} + +void enter(const char* msg,std::string& str) +{ + std::cout<<msg; + std::getline(std::cin,str); +} + +void enter(const char* msg,shared_string& str) +{ + std::cout<<msg; + std::string stdstr; + std::getline(std::cin,stdstr); + str=stdstr.c_str(); +} + +int main() +{ + /* Create (or open) the memory mapped file where the book container + * is stored, along with a mutex for synchronized access. + */ + + bip::managed_mapped_file seg( + bip::open_or_create,"./book_container.db", + 65536); + bip::named_mutex mutex( + bip::open_or_create,"7FD6D7E8-320B-11DC-82CF-F0B655D89593"); + + /* create or open the book container in shared memory */ + + book_container* pbc=seg.find_or_construct<book_container>("book container")( + book_container::ctor_args_list(), + book_container::allocator_type(seg.get_segment_manager())); + + std::string command_info= + "1. list books by author\n" + "2. list all books by prize\n" + "3. insert a book\n" + "4. delete a book\n" + "0. exit\n"; + + std::cout<<command_info; + + /* main loop */ + + for(bool exit=false;!exit;){ + int command=-1; + enter("command: ",command); + + switch(command){ + case 0:{ /* exit */ + exit=true; + break; + } + case 1:{ /* list books by author */ + std::string author; + enter("author (empty=all authors): ",author); + + /* operations with the container must be mutex protected */ + + bip::scoped_lock<bip::named_mutex> lock(mutex); + + std::pair<book_container::iterator,book_container::iterator> rng; + if(author.empty()){ + rng=std::make_pair(pbc->begin(),pbc->end()); + } + else{ + rng=pbc->equal_range( + shared_string( + author.c_str(), + shared_string::allocator_type(seg.get_segment_manager()))); + } + + if(rng.first==rng.second){ + std::cout<<"no entries\n"; + } + else{ + std::copy( + rng.first,rng.second,std::ostream_iterator<book>(std::cout)); + } + break; + } + case 2:{ /* list all books by prize */ + bip::scoped_lock<bip::named_mutex> lock(mutex); + + std::copy( + get<2>(*pbc).begin(),get<2>(*pbc).end(), + std::ostream_iterator<book>(std::cout)); + break; + } + case 3:{ /* insert a book */ + book b(shared_string::allocator_type(seg.get_segment_manager())); + + enter("author: ",b.author); + enter("name: " ,b.name); + enter("prize: " ,b.prize); + enter("pages: " ,b.pages); + + std::cout<<"insert the following?\n"<<b<<"(y/n): "; + char yn='n'; + enter("",yn); + if(yn=='y'||yn=='Y'){ + bip::scoped_lock<bip::named_mutex> lock(mutex); + pbc->insert(b); + } + + break; + } + case 4:{ /* delete a book */ + shared_string name( + shared_string::allocator_type(seg.get_segment_manager())); + enter( + "name of the book (you can enter\nonly the first few characters): ", + name); + + typedef nth_index<book_container,1>::type index_by_name; + index_by_name& idx=get<1>(*pbc); + index_by_name::iterator it; + book b(shared_string::allocator_type(seg.get_segment_manager())); + + { + /* Look for a book whose title begins with name. Note that we + * are unlocking after doing the search so as to not leave the + * container blocked during user prompting. That is also why a + * local copy of the book is done. + */ + + bip::scoped_lock<bip::named_mutex> lock(mutex); + + it=idx.find(partial_string(name)); + if(it==idx.end()){ + std::cout<<"no such book found\n"; + break; + } + b=*it; + } + + std::cout<<"delete the following?\n"<<b<<"(y/n): "; + char yn='n'; + enter("",yn); + if(yn=='y'||yn=='Y'){ + bip::scoped_lock<bip::named_mutex> lock(mutex); + idx.erase(it); + } + + break; + } + default:{ + std::cout<<"select one option:\n"<<command_info; + break; + } + } + } + + return 0; +} diff --git a/src/boost/libs/multi_index/example/non_default_ctor.cpp b/src/boost/libs/multi_index/example/non_default_ctor.cpp new file mode 100644 index 000000000..afdbd5133 --- /dev/null +++ b/src/boost/libs/multi_index/example/non_default_ctor.cpp @@ -0,0 +1,96 @@ +/* Boost.MultiIndex example of use of multi_index_container::ctor_args_list. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <algorithm> +#include <iostream> +#include <iterator> + +using boost::multi_index_container; +using namespace boost::multi_index; + +/* modulo_less order numbers according to their division residual. + * For instance, if modulo==10 then 22 is less than 15 as 22%10==2 and + * 15%10==5. + */ + +template<typename IntegralType> +struct modulo_less +{ + modulo_less(IntegralType m):modulo(m){} + + bool operator()(IntegralType x,IntegralType y)const + { + return (x%modulo)<(y%modulo); + } + +private: + IntegralType modulo; +}; + +/* multi_index_container of unsigned ints holding a "natural" index plus + * an ordering based on modulo_less. + */ + +typedef multi_index_container< + unsigned int, + indexed_by< + ordered_unique<identity<unsigned int> >, + ordered_non_unique<identity<unsigned int>, modulo_less<unsigned int> > + > +> modulo_indexed_set; + +int main() +{ + /* define a modulo_indexed_set with modulo==10 */ + + modulo_indexed_set::ctor_args_list args_list= + boost::make_tuple( + /* ctor_args for index #0 is default constructible */ + nth_index<modulo_indexed_set,0>::type::ctor_args(), + + /* first parm is key_from_value, second is our sought for key_compare */ + boost::make_tuple(identity<unsigned int>(),modulo_less<unsigned int>(10)) + ); + + modulo_indexed_set m(args_list); + /* this could have be written online without the args_list variable, + * left as it is for explanatory purposes. */ + + /* insert some numbers */ + + unsigned int numbers[]={0,1,20,40,33,68,11,101,60,34,88,230,21,4,7,17}; + const std::size_t numbers_length(sizeof(numbers)/sizeof(numbers[0])); + + m.insert(&numbers[0],&numbers[numbers_length]); + + /* lists all numbers in order, along with their "equivalence class", that is, + * the equivalent numbers under modulo_less + */ + + for(modulo_indexed_set::iterator it=m.begin();it!=m.end();++it){ + std::cout<<*it<<" -> ( "; + + nth_index<modulo_indexed_set,1>::type::iterator it0,it1; + boost::tie(it0,it1)=get<1>(m).equal_range(*it); + std::copy(it0,it1,std::ostream_iterator<unsigned int>(std::cout," ")); + + std::cout<<")"<<std::endl; + } + + return 0; +} diff --git a/src/boost/libs/multi_index/example/random_access.cpp b/src/boost/libs/multi_index/example/random_access.cpp new file mode 100644 index 000000000..7532c6d9d --- /dev/null +++ b/src/boost/libs/multi_index/example/random_access.cpp @@ -0,0 +1,102 @@ +/* Boost.MultiIndex example of use of random access indices. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/random_access_index.hpp> +#include <boost/tokenizer.hpp> +#include <algorithm> +#include <iostream> +#include <iterator> +#include <string> + +using boost::multi_index_container; +using namespace boost::multi_index; + +/* text_container holds words as inserted and also keep them indexed + * by dictionary order. + */ + +typedef multi_index_container< + std::string, + indexed_by< + random_access<>, + ordered_non_unique<identity<std::string> > + > +> text_container; + +/* ordered index */ + +typedef nth_index<text_container,1>::type ordered_text; + +/* Helper function for obtaining the position of an element in the + * container. + */ + +template<typename IndexIterator> +text_container::size_type text_position( + const text_container& tc,IndexIterator it) +{ + /* project to the base index and calculate offset from begin() */ + + return project<0>(tc,it)-tc.begin(); +} + +typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer; + +int main() +{ + std::string text= + "'Oh, you wicked little thing!' cried Alice, catching up the kitten, " + "and giving it a little kiss to make it understand that it was in " + "disgrace. 'Really, Dinah ought to have taught you better manners! You " + "ought, Dinah, you know you ought!' she added, looking reproachfully at " + "the old cat, and speaking in as cross a voice as she could manage " + "-- and then she scrambled back into the armchair, taking the kitten and " + "the worsted with her, and began winding up the ball again. But she " + "didn't get on very fast, as she was talking all the time, sometimes to " + "the kitten, and sometimes to herself. Kitty sat very demurely on her " + "knee, pretending to watch the progress of the winding, and now and then " + "putting out one paw and gently touching the ball, as if it would be glad " + "to help, if it might."; + + /* feed the text into the container */ + + text_container tc; + tc.reserve(text.size()); /* makes insertion faster */ + text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-")); + std::copy(tok.begin(),tok.end(),std::back_inserter(tc)); + + std::cout<<"enter a position (0-"<<tc.size()-1<<"):"; + text_container::size_type pos=tc.size(); + std::cin>>pos; + if(pos>=tc.size()){ + std::cout<<"out of bounds"<<std::endl; + } + else{ + std::cout<<"the word \""<<tc[pos]<<"\" appears at position(s): "; + + std::pair<ordered_text::iterator,ordered_text::iterator> p= + get<1>(tc).equal_range(tc[pos]); + while(p.first!=p.second){ + std::cout<<text_position(tc,p.first++)<<" "; + } + + std::cout<<std::endl; + } + + return 0; +} diff --git a/src/boost/libs/multi_index/example/rearrange.cpp b/src/boost/libs/multi_index/example/rearrange.cpp new file mode 100644 index 000000000..31388513d --- /dev/null +++ b/src/boost/libs/multi_index/example/rearrange.cpp @@ -0,0 +1,265 @@ +/* Boost.MultiIndex example of use of rearrange facilities. + * + * Copyright 2003-2015 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/config.hpp> +#include <boost/detail/iterator.hpp> +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/random_access_index.hpp> +#include <boost/random/binomial_distribution.hpp> +#include <boost/random/uniform_real.hpp> +#include <boost/random/mersenne_twister.hpp> +#include <algorithm> +#include <iostream> +#include <iterator> +#include <vector> + +#if !defined(BOOST_NO_CXX11_HDR_RANDOM) +#include <random> +#endif + +using boost::multi_index_container; +using namespace boost::multi_index; + +/* We model a card deck with a random access array containing + * card numbers (from 0 to 51), supplemented with an additional + * index which retains the start ordering. + */ + +class deck +{ + BOOST_STATIC_CONSTANT(std::size_t,num_cards=52); + + typedef multi_index_container< + int, + indexed_by< + random_access<>, /* base index */ + random_access<> /* "start" index */ + > + > container_type; + container_type cont; + +public: + deck() + { + cont.reserve(num_cards); + get<1>(cont).reserve(num_cards); + for(std::size_t i=0;i<num_cards;++i)cont.push_back(i); + } + + typedef container_type::iterator iterator; + typedef container_type::size_type size_type; + + iterator begin()const{return cont.begin();} + iterator end()const{return cont.end();} + size_type size()const{return cont.size();} + + template<typename InputIterator> + void rearrange(InputIterator it) + { + cont.rearrange(it); + } + + void reset() + { + /* simply rearrange the base index like the start index */ + + cont.rearrange(get<1>(cont).begin()); + } + + std::size_t position(int i)const + { + /* The position of a card in the deck is calculated by locating + * the card through the start index (which is ordered), projecting + * to the base index and diffing with the begin position. + * Resulting complexity: constant. + */ + + return project<0>(cont,get<1>(cont).begin()+i)-cont.begin(); + } + + std::size_t rising_sequences()const + { + /* Iterate through all cards and increment the sequence count + * when the current position is left to the previous. + * Resulting complexity: O(n), n=num_cards. + */ + + std::size_t s=1; + std::size_t last_pos=0; + + for(std::size_t i=0;i<num_cards;++i){ + std::size_t pos=position(i); + if(pos<last_pos)++s; + last_pos=pos; + } + + return s; + } +}; + +/* A vector of reference_wrappers to deck elements can be used + * as a view to the deck container. + * We use a special implicit_reference_wrapper having implicit + * ctor from its base type, as this simplifies the use of generic + * techniques on the resulting data structures. + */ + +template<typename T> +class implicit_reference_wrapper:public boost::reference_wrapper<T> +{ +private: + typedef boost::reference_wrapper<T> super; +public: + implicit_reference_wrapper(T& t):super(t){} +}; + +typedef std::vector<implicit_reference_wrapper<const int> > deck_view; + +/* Riffle shuffle is modeled like this: A cut is selected in the deck + * following a binomial distribution. Then, cards are randomly selected + * from one packet or the other with probability proportional to + * packet size. + */ + +template<typename RandomAccessIterator,typename OutputIterator> +void riffle_shuffle( + RandomAccessIterator first,RandomAccessIterator last, + OutputIterator out) +{ + static boost::mt19937 rnd_gen; + + typedef typename boost::detail::iterator_traits< + RandomAccessIterator>::difference_type difference_type; + typedef boost::binomial_distribution< + difference_type> rnd_cut_select_type; + typedef boost::uniform_real<> rnd_deck_select_type; + + rnd_cut_select_type cut_select(last-first); + RandomAccessIterator middle=first+cut_select(rnd_gen); + difference_type s0=middle-first; + difference_type s1=last-middle; + rnd_deck_select_type deck_select; + + while(s0!=0&&s1!=0){ + if(deck_select(rnd_gen)<(double)s0/(s0+s1)){ + *out++=*first++; + --s0; + } + else{ + *out++=*middle++; + --s1; + } + } + std::copy(first,first+s0,out); + std::copy(middle,middle+s1,out); +} + +struct riffle_shuffler +{ + void operator()(deck& d)const + { + dv.clear(); + dv.reserve(d.size()); + riffle_shuffle( + d.begin(),d.end(),std::back_inserter(dv)); /* do the shuffling */ + d.rearrange(dv.begin()); /* apply to the deck */ + } + +private: + mutable deck_view dv; +}; + +/* A truly random shuffle (up to stdlib implementation quality) using + * std::shuffle. + */ + +struct random_shuffler +{ + void operator()(deck& d) + { + dv.clear(); + dv.reserve(d.size()); + std::copy(d.begin(),d.end(),std::back_inserter(dv)); + shuffle_view(); + d.rearrange(dv.begin()); /* apply to the deck */ + } + +private: + deck_view dv; + +#if !defined(BOOST_NO_CXX11_HDR_RANDOM) + std::mt19937 e; + + void shuffle_view() + { + std::shuffle(dv.begin(),dv.end(),e); + } +#else + /* for pre-C++11 compilers we use std::random_shuffle */ + + void shuffle_view() + { + std::random_shuffle(dv.begin(),dv.end()); + } +#endif +}; + +/* Repeat a given shuffling algorithm repeats_num times + * and obtain the resulting rising sequences number. Average + * for tests_num trials. + */ + +template<typename Shuffler> +double shuffle_test( + unsigned int repeats_num,unsigned int tests_num + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Shuffler)) +{ + deck d; + Shuffler sh; + unsigned long total=0; + + for(unsigned int n=0;n<tests_num;++n){ + for(unsigned m=0;m<repeats_num;++m)sh(d); + total+=d.rising_sequences(); + d.reset(); + } + + return (double)total/tests_num; +} + +int main() +{ + unsigned rifs_num=0; + unsigned tests_num=0; + + std::cout<<"number of riffle shuffles (vg 5):"; + std::cin>>rifs_num; + std::cout<<"number of tests (vg 1000):"; + std::cin>>tests_num; + + std::cout<<"shuffling..."<<std::endl; + + std::cout<<"riffle shuffling\n" + " avg number of rising sequences: " + <<shuffle_test<riffle_shuffler>(rifs_num,tests_num) + <<std::endl; + + std::cout<<"random shuffling\n" + " avg number of rising sequences: " + <<shuffle_test<random_shuffler>(1,tests_num) + <<std::endl; + + return 0; +} diff --git a/src/boost/libs/multi_index/example/sequenced.cpp b/src/boost/libs/multi_index/example/sequenced.cpp new file mode 100644 index 000000000..14651da4f --- /dev/null +++ b/src/boost/libs/multi_index/example/sequenced.cpp @@ -0,0 +1,100 @@ +/* Boost.MultiIndex example of use of sequenced indices. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/tokenizer.hpp> +#include <algorithm> +#include <iomanip> +#include <iostream> +#include <iterator> +#include <string> + +using boost::multi_index_container; +using namespace boost::multi_index; + +/* text_container holds words as inserted and also keep them indexed + * by dictionary order. + */ + +typedef multi_index_container< + std::string, + indexed_by< + sequenced<>, + ordered_non_unique<identity<std::string> > + > +> text_container; + +/* ordered index */ + +typedef nth_index<text_container,1>::type ordered_text; + +typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer; + +int main() +{ + std::string text= + "Alice was beginning to get very tired of sitting by her sister on the " + "bank, and of having nothing to do: once or twice she had peeped into the " + "book her sister was reading, but it had no pictures or conversations in " + "it, 'and what is the use of a book,' thought Alice 'without pictures or " + "conversation?'"; + + /* feed the text into the container */ + + text_container tc; + text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-")); + std::copy(tok.begin(),tok.end(),std::back_inserter(tc)); + + /* list all words in alphabetical order along with their number + * of occurrences + */ + + ordered_text& ot=get<1>(tc); + for(ordered_text::iterator it=ot.begin();it!=ot.end();){ + std::cout<<std::left<<std::setw(14)<<*it<<":"; /* print the word */ + ordered_text::iterator it2=ot.upper_bound(*it); /* jump to next */ + std::cout<<std::right<<std::setw(3) /* and compute the distance */ + <<std::distance(it,it2)<<" times"<<std::endl; + it=it2; + } + + /* reverse the text and print it out */ + + tc.reverse(); + std::cout<<std::endl; + std::copy( + tc.begin(),tc.end(),std::ostream_iterator<std::string>(std::cout," ")); + std::cout<<std::endl; + tc.reverse(); /* undo */ + + /* delete most common English words and print the result */ + + std::string common_words[]= + {"the","of","and","a","to","in","is","you","that","it", + "he","for","was","on","are","as","with","his","they","at"}; + + for(std::size_t n=0;n<sizeof(common_words)/sizeof(common_words[0]);++n){ + ot.erase(common_words[n]); + } + std::cout<<std::endl; + std::copy( + tc.begin(),tc.end(),std::ostream_iterator<std::string>(std::cout," ")); + std::cout<<std::endl; + + return 0; +} diff --git a/src/boost/libs/multi_index/example/serialization.cpp b/src/boost/libs/multi_index/example/serialization.cpp new file mode 100644 index 000000000..46ccf508e --- /dev/null +++ b/src/boost/libs/multi_index/example/serialization.cpp @@ -0,0 +1,144 @@ +/* Boost.MultiIndex example of serialization of a MRU list. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#if !defined(NDEBUG) +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <boost/archive/text_oarchive.hpp> +#include <boost/archive/text_iarchive.hpp> +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <fstream> +#include <iostream> +#include <iterator> +#include <sstream> +#include <string> + +using namespace boost::multi_index; + +/* An MRU (most recently used) list keeps record of the last n + * inserted items, listing first the newer ones. Care has to be + * taken when a duplicate item is inserted: instead of letting it + * appear twice, the MRU list relocates it to the first position. + */ + +template <typename Item> +class mru_list +{ + typedef multi_index_container< + Item, + indexed_by< + sequenced<>, + hashed_unique<identity<Item> > + > + > item_list; + +public: + typedef Item item_type; + typedef typename item_list::iterator iterator; + + mru_list(std::size_t max_num_items_):max_num_items(max_num_items_){} + + void insert(const item_type& item) + { + std::pair<iterator,bool> p=il.push_front(item); + + if(!p.second){ /* duplicate item */ + il.relocate(il.begin(),p.first); /* put in front */ + } + else if(il.size()>max_num_items){ /* keep the length <= max_num_items */ + il.pop_back(); + } + } + + iterator begin(){return il.begin();} + iterator end(){return il.end();} + + /* Utilities to save and load the MRU list, internally + * based on Boost.Serialization. + */ + + void save_to_file(const char* file_name)const + { + std::ofstream ofs(file_name); + boost::archive::text_oarchive oa(ofs); + oa<<boost::serialization::make_nvp("mru",*this); + } + + void load_from_file(const char* file_name) + { + std::ifstream ifs(file_name); + if(ifs){ + boost::archive::text_iarchive ia(ifs); + ia>>boost::serialization::make_nvp("mru",*this); + } + } + +private: + item_list il; + std::size_t max_num_items; + + /* serialization support */ + + friend class boost::serialization::access; + + template<class Archive> + void serialize(Archive& ar,const unsigned int) + { + ar&BOOST_SERIALIZATION_NVP(il); + ar&BOOST_SERIALIZATION_NVP(max_num_items); + } +}; + +int main() +{ + const char* mru_store="mru_store"; + + /* Construct a MRU limited to 10 items and retrieve its + * previous contents. + */ + + mru_list<std::string> mru(10); + mru.load_from_file(mru_store); + + /* main loop */ + + for(;;){ + std::cout<<"enter a term: "; + + std::string line; + std::getline(std::cin,line); + if(line.empty())break; + + std::string term; + std::istringstream iss(line); + iss>>term; + if(term.empty())break; + + mru.insert(term); + + std::cout<<"most recently entered terms:"<<std::endl; + std::copy( + mru.begin(),mru.end(), + std::ostream_iterator<std::string>(std::cout,"\n")); + } + + /* persist the MRU list */ + + mru.save_to_file(mru_store); + + return 0; +} diff --git a/src/boost/libs/multi_index/index.html b/src/boost/libs/multi_index/index.html new file mode 100644 index 000000000..c190fc1e6 --- /dev/null +++ b/src/boost/libs/multi_index/index.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN"> +<!-- + Copyright 2003-2004 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/index.html"> +<title>Boost.MultiIndex Documentation</title> +<link rel="stylesheet" href="doc/style.css" type="text/css"> +</head> + +<body> +Automatic redirection failed, please go to +<a href="doc/index.html">doc/index.html</a> +</body> +</html> diff --git a/src/boost/libs/multi_index/meta/libraries.json b/src/boost/libs/multi_index/meta/libraries.json new file mode 100644 index 000000000..8f0df7493 --- /dev/null +++ b/src/boost/libs/multi_index/meta/libraries.json @@ -0,0 +1,15 @@ +{ + "key": "multi_index", + "name": "Multi-Index", + "authors": [ + "Joaqu\u00edn M L\u00f3pez Mu\u00f1oz" + ], + "description": "The Boost Multi-index Containers Library provides a class template named multi_index_container which enables the construction of containers maintaining one or more indices with different sorting and access semantics.", + "category": [ + "Containers", + "Data" + ], + "maintainers": [ + "Joaquin M Lopez Munoz <joaquin.lopezmunoz -at- gmail.com>" + ] +} diff --git a/src/boost/libs/multi_index/perf/Jamfile.v2 b/src/boost/libs/multi_index/perf/Jamfile.v2 new file mode 100644 index 000000000..c9aea9c7c --- /dev/null +++ b/src/boost/libs/multi_index/perf/Jamfile.v2 @@ -0,0 +1,14 @@ +# Boost.MultiIndex performance tests Jamfile +# +# Copyright 2003-2006 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) +# +# See http://www.boost.org/libs/multi_index for library home page. + +exe test_perf + : test_perf.cpp + : <include>$(BOOST_ROOT) + : release + ; diff --git a/src/boost/libs/multi_index/perf/test_perf.cpp b/src/boost/libs/multi_index/perf/test_perf.cpp new file mode 100644 index 000000000..7b2441787 --- /dev/null +++ b/src/boost/libs/multi_index/perf/test_perf.cpp @@ -0,0 +1,545 @@ +/* Boost.MultiIndex performance test. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ + +#include <algorithm> +#include <assert.h> +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/next_prior.hpp> +#include <climits> +#include <ctime> +#include <iomanip> +#include <iostream> +#include <list> +#include <set> +#include <string> +#include <vector> + +using namespace std; +using namespace boost::multi_index; + +/* Measurement harness by Andrew Koenig, extracted from companion code to + * Stroustrup, B.: "Wrapping C++ Member Function Calls", The C++ Report, + * June 2000, Vol 12/No 6. + * Original code retrievable at: http://www.research.att.com/~bs/wrap_code.cpp + */ + +// How many clock units does it take to interrogate the clock? +static double clock_overhead() +{ + clock_t k = clock(), start, limit; + + // Wait for the clock to tick + do start = clock(); + while (start == k); + + // interrogate the clock until it has advanced at least a second + // (for reasonable accuracy) + limit = start + CLOCKS_PER_SEC; + + unsigned long r = 0; + while ((k = clock()) < limit) + ++r; + + return double(k - start) / r; +} + +// We'd like the odds to be factor:1 that the result is +// within percent% of the median +const int factor = 10; +const int percent = 20; + +// Measure a function (object) factor*2 times, +// appending the measurements to the second argument +template<class F> +void measure_aux(F f, vector<double>& mv) +{ + static double ovhd = clock_overhead(); + + // Ensure we don't reallocate in mid-measurement + mv.reserve(mv.size() + factor*2); + + // Wait for the clock to tick + clock_t k = clock(); + clock_t start; + + do start = clock(); + while (start == k); + + // Do 2*factor measurements + for (int i = 2*factor; i; --i) { + unsigned long count = 0, limit = 1, tcount = 0; + + // Original code used CLOCKS_PER_SEC/100 + const clock_t clocklimit = start + CLOCKS_PER_SEC/10; + clock_t t; + + do { + while (count < limit) { + f(); + ++count; + } + limit *= 2; + ++tcount; + } while ((t = clock()) < clocklimit); + + // Wait for the clock to tick again; + clock_t t2; + do ++tcount; + while ((t2 = clock()) == t); + + // Append the measurement to the vector + mv.push_back(((t2 - start) - (tcount * ovhd)) / count); + + // Establish a new starting point + start = t2; + } +} + +// Returns the number of clock units per iteration +// With odds of factor:1, the measurement is within percent% of +// the value returned, which is also the median of all measurements. +template<class F> +double measure(F f) +{ + vector<double> mv; + + int n = 0; // iteration counter + do { + ++n; + + // Try 2*factor measurements + measure_aux(f, mv); + assert(mv.size() == 2*n*factor); + + // Compute the median. We know the size is even, so we cheat. + sort(mv.begin(), mv.end()); + double median = (mv[n*factor] + mv[n*factor-1])/2; + + // If the extrema are within threshold of the median, we're done + if (mv[n] > (median * (100-percent))/100 && + mv[mv.size() - n - 1] < (median * (100+percent))/100) + return median; + + } while (mv.size() < factor * 200); + + // Give up! + clog << "Help!\n\n"; + exit(1); +} + +/* dereferencing compare predicate */ + +template <typename Iterator,typename Compare> +struct it_compare +{ + bool operator()(const Iterator& x,const Iterator& y)const{return comp(*x,*y);} + +private: + Compare comp; +}; + +/* list_wrapper and multiset_wrapper adapt std::lists and std::multisets + * to make them conform to a set-like insert interface which test + * routines do assume. + */ + +template <typename List> +struct list_wrapper:List +{ + typedef typename List::value_type value_type; + typedef typename List::iterator iterator; + + pair<iterator,bool> insert(const value_type& v) + { + List::push_back(v); + return pair<iterator,bool>(boost::prior(List::end()),true); + } +}; + +template <typename Multiset> +struct multiset_wrapper:Multiset +{ + typedef typename Multiset::value_type value_type; + typedef typename Multiset::iterator iterator; + + pair<iterator,bool> insert(const value_type& v) + { + return pair<iterator,bool>(Multiset::insert(v),true); + } +}; + +/* space comsumption of manual simulations is determined by checking + * the node sizes of the containers involved. This cannot be done in a + * portable manner, so node_size has to be written on a per stdlibrary + * basis. Add your own versions if necessary. + */ + +#if defined(BOOST_DINKUMWARE_STDLIB) + +template<typename Container> +size_t node_size(const Container&) +{ + return sizeof(*Container().begin()._Mynode()); +} + +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) + +template<typename Container> +size_t node_size(const Container&) +{ + typedef typename Container::iterator::_Link_type node_ptr; + node_ptr p=0; + return sizeof(*p); +} + +template<typename Value,typename Allocator> +size_t node_size(const list<Value,Allocator>&) +{ + return sizeof(typename list<Value,Allocator>::iterator::_Node); +} + +template<typename List> +size_t node_size(const list_wrapper<List>&) +{ + return sizeof(typename List::iterator::_Node); +} + +#else + +/* default version returns 0 by convention */ + +template<typename Container> +size_t node_size(const Container&) +{ + return 0; +} + +#endif + +/* mono_container runs the tested routine on multi_index and manual + * simulations comprised of one standard container. + * bi_container and tri_container run the equivalent routine for manual + * compositions of two and three standard containers, respectively. + */ + +template <typename Container> +struct mono_container +{ + mono_container(int n_):n(n_){} + + void operator()() + { + typedef typename Container::iterator iterator; + + Container c; + + for(int i=0;i<n;++i)c.insert(i); + for(iterator it=c.begin();it!=c.end();)c.erase(it++); + } + + static size_t multi_index_node_size() + { + return sizeof(*Container().begin().get_node()); + } + + static size_t node_size() + { + return ::node_size(Container()); + } + +private: + int n; +}; + +template <typename Container1,typename Container2> +struct bi_container +{ + bi_container(int n_):n(n_){} + + void operator()() + { + typedef typename Container1::iterator iterator1; + typedef typename Container2::iterator iterator2; + + Container1 c1; + Container2 c2; + + for(int i=0;i<n;++i){ + iterator1 it1=c1.insert(i).first; + c2.insert(it1); + } + for(iterator2 it2=c2.begin();it2!=c2.end();) + { + c1.erase(*it2); + c2.erase(it2++); + } + } + + static size_t node_size() + { + return ::node_size(Container1())+::node_size(Container2()); + } + +private: + int n; +}; + +template <typename Container1,typename Container2,typename Container3> +struct tri_container +{ + tri_container(int n_):n(n_){} + + void operator()() + { + typedef typename Container1::iterator iterator1; + typedef typename Container2::iterator iterator2; + typedef typename Container3::iterator iterator3; + + Container1 c1; + Container2 c2; + Container3 c3; + + for(int i=0;i<n;++i){ + iterator1 it1=c1.insert(i).first; + iterator2 it2=c2.insert(it1).first; + c3.insert(it2); + } + for(iterator3 it3=c3.begin();it3!=c3.end();) + { + c1.erase(**it3); + c2.erase(*it3); + c3.erase(it3++); + } + } + + static size_t node_size() + { + return ::node_size(Container1())+ + ::node_size(Container2())+::node_size(Container3()); + } + +private: + int n; +}; + +/* measure and compare two routines for several numbers of elements + * and also estimates relative memory consumption. + */ + +template <typename IndexedTest,typename ManualTest> +void run_tests(const char* title) +{ + cout<<fixed<<setprecision(2); + cout<<title<<endl; + int n=1000; + for(int i=0;i<3;++i){ + double indexed_t=measure(IndexedTest(n)); + double manual_t=measure(ManualTest(n)); + cout<<" 10^"<<i+3<<" elmts: " + <<setw(6)<<100.0*indexed_t/manual_t<<"% " + <<"(" + <<setw(6)<<1000.0*indexed_t/CLOCKS_PER_SEC<<" ms / " + <<setw(6)<<1000.0*manual_t/CLOCKS_PER_SEC<<" ms)" + <<endl; + n*=10; + } + + size_t indexed_t_node_size=IndexedTest::multi_index_node_size(); + size_t manual_t_node_size=ManualTest::node_size(); + + if(manual_t_node_size){ + cout<<" space gain: " + <<setw(6)<<100.0*indexed_t_node_size/manual_t_node_size<<"%"<<endl; + } +} + +/* compare_structures accept a multi_index_container instantiation and + * several standard containers, builds a manual simulation out of the + * latter and run the tests. + */ + +template <typename IndexedType,typename ManualType> +void compare_structures(const char* title) +{ + run_tests< + mono_container<IndexedType>, + mono_container<ManualType> + >(title); +} + +template <typename IndexedType,typename ManualType1,typename ManualType2> +void compare_structures2(const char* title) +{ + run_tests< + mono_container<IndexedType>, + bi_container<ManualType1,ManualType2> + >(title); +} + +template < + typename IndexedType, + typename ManualType1,typename ManualType2,typename ManualType3 +> +void compare_structures3(const char* title) +{ + run_tests< + mono_container<IndexedType>, + tri_container<ManualType1,ManualType2,ManualType3> + >(title); +} + +int main() +{ + /* some stdlibs provide the discussed but finally rejected std::identity */ + using boost::multi_index::identity; + + { + /* 1 ordered index */ + + typedef multi_index_container<int> indexed_t; + typedef set<int> manual_t; + + compare_structures<indexed_t,manual_t>( + "1 ordered index"); + } + { + /* 1 sequenced index */ + + typedef list_wrapper< + multi_index_container< + int, + indexed_by<sequenced<> > + > + > indexed_t; + typedef list_wrapper<list<int> > manual_t; + + compare_structures<indexed_t,manual_t>( + "1 sequenced index"); + } + { + /* 2 ordered indices */ + + typedef multi_index_container< + int, + indexed_by< + ordered_unique<identity<int> >, + ordered_non_unique<identity<int> > + > + > indexed_t; + typedef set<int> manual_t1; + typedef multiset< + manual_t1::iterator, + it_compare< + manual_t1::iterator, + manual_t1::key_compare + > + > manual_t2; + + compare_structures2<indexed_t,manual_t1,manual_t2>( + "2 ordered indices"); + } + { + /* 1 ordered index + 1 sequenced index */ + + typedef multi_index_container< + int, + indexed_by< + boost::multi_index::ordered_unique<identity<int> >, + sequenced<> + > + > indexed_t; + typedef list_wrapper< + list<int> + > manual_t1; + typedef multiset< + manual_t1::iterator, + it_compare< + manual_t1::iterator, + std::less<int> + > + > manual_t2; + + compare_structures2<indexed_t,manual_t1,manual_t2>( + "1 ordered index + 1 sequenced index"); + } + { + /* 3 ordered indices */ + + typedef multi_index_container< + int, + indexed_by< + ordered_unique<identity<int> >, + ordered_non_unique<identity<int> >, + ordered_non_unique<identity<int> > + > + > indexed_t; + typedef set<int> manual_t1; + typedef multiset_wrapper< + multiset< + manual_t1::iterator, + it_compare< + manual_t1::iterator, + manual_t1::key_compare + > + > + > manual_t2; + typedef multiset< + manual_t2::iterator, + it_compare< + manual_t2::iterator, + manual_t2::key_compare + > + > manual_t3; + + compare_structures3<indexed_t,manual_t1,manual_t2,manual_t3>( + "3 ordered indices"); + } + { + /* 2 ordered indices + 1 sequenced index */ + + typedef multi_index_container< + int, + indexed_by< + ordered_unique<identity<int> >, + ordered_non_unique<identity<int> >, + sequenced<> + > + > indexed_t; + typedef list_wrapper< + list<int> + > manual_t1; + typedef multiset_wrapper< + multiset< + manual_t1::iterator, + it_compare< + manual_t1::iterator, + std::less<int> + > + > + > manual_t2; + typedef multiset< + manual_t2::iterator, + it_compare< + manual_t2::iterator, + manual_t2::key_compare + > + > manual_t3; + + compare_structures3<indexed_t,manual_t1,manual_t2,manual_t3>( + "2 ordered indices + 1 sequenced index"); + } + + return 0; +} diff --git a/src/boost/libs/multi_index/test/Jamfile.v2 b/src/boost/libs/multi_index/test/Jamfile.v2 new file mode 100644 index 000000000..405dc7656 --- /dev/null +++ b/src/boost/libs/multi_index/test/Jamfile.v2 @@ -0,0 +1,75 @@ +# Boost.MultiIndex tests Jamfile +# +# Copyright 2003-2020 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) +# +# See http://www.boost.org/libs/multi_index for library home page. + +import os ; +import type ; + +# Windows Vista UAC has an heuristic by which executable files whose name +# contains any of the words "install", "setup", "update", etc. are assumed +# to be installation packages needing administrative rights, which causes +# the system to bring up a window asking for execution confirmation by the +# user, thus interferring in the unattended bjam process. +# Problem bypassed by changing the EXE names containing a taboo word. +# Thanks to Rene Rivera for guidance on the use of the <tag> feature. + +rule change-test_update-exe-name ( name : type ? : property-set ) +{ + if [ os.on-windows ] && [ type.is-subtype $(type) EXE ] + { + return test_updat.exe ; + } +} + +project + : requirements + <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS + <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS + <toolset>msvc:<define>_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS + <toolset>msvc:<cxxflags>/wd4494 + ; + +obj boost_multi_index_key_supported : check_bmi_key_supported.cpp ; +explicit boost_multi_index_key_supported ; + +test-suite "multi_index" : + [ run test_alloc_awareness.cpp test_alloc_awareness_main.cpp ] + [ run test_basic.cpp test_basic_main.cpp ] + [ run test_capacity.cpp test_capacity_main.cpp ] + [ run test_comparison.cpp test_comparison_main.cpp ] + [ run test_composite_key.cpp test_composite_key_main.cpp ] + [ run test_conv_iterators.cpp test_conv_iterators_main.cpp ] + [ run test_copy_assignment.cpp test_copy_assignment_main.cpp ] + [ run test_hash_ops.cpp test_hash_ops_main.cpp ] + [ run test_iterators.cpp test_iterators_main.cpp ] + [ run test_key.cpp test_key_main.cpp + : : : + [ check-target-builds boost_multi_index_key_supported + "BOOST_MULTI_INDEX_KEY_SUPPORTED defined" + : : <build>no ] ] + [ run test_key_extractors.cpp test_key_extractors_main.cpp ] + [ run test_list_ops.cpp test_list_ops_main.cpp ] + [ run test_modifiers.cpp test_modifiers_main.cpp ] + [ run test_mpl_ops.cpp test_mpl_ops_main.cpp ] + [ run test_observers.cpp test_observers_main.cpp ] + [ run test_projection.cpp test_projection_main.cpp ] + [ run test_range.cpp test_range_main.cpp ] + [ run test_rank_ops.cpp test_rank_ops_main.cpp ] + [ run test_rearrange.cpp test_rearrange_main.cpp ] + [ run test_safe_mode.cpp test_safe_mode_main.cpp ] + [ run test_serialization.cpp test_serialization1.cpp + test_serialization2.cpp test_serialization3.cpp + test_serialization_main.cpp + /boost/serialization//boost_serialization ] + [ run test_set_ops.cpp test_set_ops_main.cpp ] + [ run test_special_set_ops.cpp test_special_set_ops_main.cpp ] + [ run test_update.cpp test_update_main.cpp + : : : + -<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag + <tag>@change-test_update-exe-name ] + ; diff --git a/src/boost/libs/multi_index/test/check_bmi_key_supported.cpp b/src/boost/libs/multi_index/test/check_bmi_key_supported.cpp new file mode 100644 index 000000000..99ce8694b --- /dev/null +++ b/src/boost/libs/multi_index/test/check_bmi_key_supported.cpp @@ -0,0 +1,13 @@ +/* Copyright 2003-2018 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/multi_index for library home page. + */ + +#include <boost/multi_index/key.hpp> + +#if !defined(BOOST_MULTI_INDEX_KEY_SUPPORTED) +#error BOOST_MULTI_INDEX_KEY_SUPPORTED macro not defined +#endif diff --git a/src/boost/libs/multi_index/test/employee.hpp b/src/boost/libs/multi_index/test/employee.hpp new file mode 100644 index 000000000..3a63c02e8 --- /dev/null +++ b/src/boost/libs/multi_index/test/employee.hpp @@ -0,0 +1,152 @@ +/* Used in Boost.MultiIndex tests. + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +#ifndef BOOST_MULTI_INDEX_TEST_EMPLOYEE_HPP +#define BOOST_MULTI_INDEX_TEST_EMPLOYEE_HPP + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/move/core.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/random_access_index.hpp> +#include <boost/multi_index/ranked_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <ostream> +#include <string> +#include "non_std_allocator.hpp" + +struct employee +{ + int id; + std::string name; + int age; + int ssn; + + employee(int id_,std::string name_,int age_,int ssn_): + id(id_),name(name_),age(age_),ssn(ssn_) + {} + + employee(const employee& x): + id(x.id),name(x.name),age(x.age),ssn(x.ssn) + {} + + employee(BOOST_RV_REF(employee) x): + id(x.id),name(boost::move(x.name)),age(x.age),ssn(x.ssn) + {} + + employee& operator=(BOOST_COPY_ASSIGN_REF(employee) x) + { + id=x.id; + name=x.name; + age=x.age; + ssn=x.ssn; + return *this; + }; + + employee& operator=(BOOST_RV_REF(employee) x) + { + id=x.id; + name=boost::move(x.name); + age=x.age; + ssn=x.ssn; + return *this; + } + + bool operator==(const employee& x)const + { + return id==x.id&&name==x.name&&age==x.age; + } + + bool operator<(const employee& x)const + { + return id<x.id; + } + + bool operator!=(const employee& x)const{return !(*this==x);} + bool operator> (const employee& x)const{return x<*this;} + bool operator>=(const employee& x)const{return !(*this<x);} + bool operator<=(const employee& x)const{return !(x<*this);} + + struct comp_id + { + bool operator()(int x,const employee& e2)const{return x<e2.id;} + bool operator()(const employee& e1,int x)const{return e1.id<x;} + }; + + friend std::ostream& operator<<(std::ostream& os,const employee& e) + { + os<<e.id<<" "<<e.name<<" "<<e.age<<std::endl; + return os; + } + +private: + BOOST_COPYABLE_AND_MOVABLE(employee) +}; + +struct name{}; +struct by_name{}; +struct age{}; +struct as_inserted{}; +struct ssn{}; +struct randomly{}; + +struct employee_set_indices: + boost::mpl::vector< + boost::multi_index::ordered_unique< + boost::multi_index::identity<employee> >, + boost::multi_index::hashed_non_unique< + boost::multi_index::tag<name,by_name>, + BOOST_MULTI_INDEX_MEMBER(employee,std::string,name)>, + boost::multi_index::ranked_non_unique< + boost::multi_index::tag<age>, + BOOST_MULTI_INDEX_MEMBER(employee,int,age)>, + boost::multi_index::sequenced< + boost::multi_index::tag<as_inserted> >, + boost::multi_index::hashed_unique< + boost::multi_index::tag<ssn>, + BOOST_MULTI_INDEX_MEMBER(employee,int,ssn)>, + boost::multi_index::random_access< + boost::multi_index::tag<randomly> > > +{}; + +typedef + boost::multi_index::multi_index_container< + employee, + employee_set_indices, + non_std_allocator<employee> > employee_set; + +#if defined(BOOST_NO_MEMBER_TEMPLATES) +typedef boost::multi_index::nth_index< + employee_set,1>::type employee_set_by_name; +#else +typedef employee_set::nth_index<1>::type employee_set_by_name; +#endif + +typedef boost::multi_index::index< + employee_set,age>::type employee_set_by_age; +typedef boost::multi_index::index< + employee_set,as_inserted>::type employee_set_as_inserted; +typedef boost::multi_index::index< + employee_set,ssn>::type employee_set_by_ssn; + +#if defined(BOOST_NO_MEMBER_TEMPLATES) +typedef boost::multi_index::index< + employee_set,randomly>::type employee_set_randomly; +#else +typedef employee_set::index< + randomly>::type employee_set_randomly; +#endif + +#endif diff --git a/src/boost/libs/multi_index/test/non_std_allocator.hpp b/src/boost/libs/multi_index/test/non_std_allocator.hpp new file mode 100644 index 000000000..80f366ca0 --- /dev/null +++ b/src/boost/libs/multi_index/test/non_std_allocator.hpp @@ -0,0 +1,141 @@ +/* Used in Boost.MultiIndex tests. + * + * Copyright 2003-2020 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/multi_index for library home page. + */ + +#ifndef BOOST_MULTI_INDEX_TEST_NON_STD_ALLOCATOR_HPP +#define BOOST_MULTI_INDEX_TEST_NON_STD_ALLOCATOR_HPP + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/throw_exception.hpp> +#include <iterator> +#include <cstddef> +#include <stdexcept> + +template<typename T> +class non_raw_pointer +{ +public: + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef std::random_access_iterator_tag iterator_category; + + non_raw_pointer(){} + explicit non_raw_pointer(T* p_):p(p_){} + + T& operator*()const + { +#if !defined(BOOST_NO_EXCEPTIONS) + if(!p)boost::throw_exception(std::runtime_error("null indirection")); +#endif + + return *p; + } + + T* operator->()const{return p;} + non_raw_pointer& operator++(){++p;return *this;} + non_raw_pointer operator++(int){non_raw_pointer t(*this);++p;return t;} + non_raw_pointer& operator--(){--p;return *this;} + non_raw_pointer operator--(int){non_raw_pointer t(*this);--p;return t;} + non_raw_pointer& operator+=(std::ptrdiff_t n){p+=n;return *this;} + non_raw_pointer& operator-=(std::ptrdiff_t n){p-=n;return *this;} + T& operator[](std::ptrdiff_t n)const{return p[n];} + + T* raw_ptr()const{return p;} + +private: + T* p; +}; + +template<typename T> +non_raw_pointer<T> operator+(const non_raw_pointer<T>& x,std::ptrdiff_t n) +{return non_raw_pointer<T>(x.raw_ptr()+n);} + +template<typename T> +non_raw_pointer<T> operator+(std::ptrdiff_t n,const non_raw_pointer<T>& x) +{return non_raw_pointer<T>(n+x.raw_ptr());} + +template<typename T> +non_raw_pointer<T> operator-(const non_raw_pointer<T>& x,std::ptrdiff_t n) +{return non_raw_pointer<T>(x.raw_ptr()-n);} + +template<typename T> +std::ptrdiff_t operator-( + const non_raw_pointer<T>& x,const non_raw_pointer<T>& y) +{return x.raw_ptr()-y.raw_ptr();} + +template<typename T> +bool operator==(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y) +{return x.raw_ptr()==y.raw_ptr();} + +template<typename T> +bool operator!=(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y) +{return x.raw_ptr()!=y.raw_ptr();} + +template<typename T> +bool operator<(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y) +{return x.raw_ptr()<y.raw_ptr();} + +template<typename T> +bool operator>(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y) +{return x.raw_ptr()>y.raw_ptr();} + +template<typename T> +bool operator>=(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y) +{return x.raw_ptr()>=y.raw_ptr();} + +template<typename T> +bool operator<=(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y) +{return x.raw_ptr()<=y.raw_ptr();} + +template<typename T> +class non_std_allocator +{ +public: + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef non_raw_pointer<T> pointer; + typedef non_raw_pointer<const T> const_pointer; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template<class U>struct rebind{typedef non_std_allocator<U> other;}; + + non_std_allocator(){} + non_std_allocator(const non_std_allocator<T>&){} + template<class U>non_std_allocator(const non_std_allocator<U>&,int=0){} + non_std_allocator& operator=(const non_std_allocator<T>&){return *this;} + + pointer allocate(size_type n) + { + return pointer((T*)(new char[n*sizeof(T)])); + } + + void deallocate(pointer p,size_type) + { + delete[](char *)&*p; + } + + size_type max_size() const{return (size_type )(-1);} + + friend bool operator==(const non_std_allocator&,const non_std_allocator&) + { + return true; + } + + friend bool operator!=(const non_std_allocator&,const non_std_allocator&) + { + return false; + } +}; + +#endif diff --git a/src/boost/libs/multi_index/test/pair_of_ints.hpp b/src/boost/libs/multi_index/test/pair_of_ints.hpp new file mode 100644 index 000000000..6089ffc34 --- /dev/null +++ b/src/boost/libs/multi_index/test/pair_of_ints.hpp @@ -0,0 +1,78 @@ +/* Used in Boost.MultiIndex tests. + * + * Copyright 2003-2010 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/multi_index for library home page. + */ + +#ifndef BOOST_MULTI_INDEX_TEST_PAIR_OF_INTS_HPP +#define BOOST_MULTI_INDEX_TEST_PAIR_OF_INTS_HPP + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/serialization/nvp.hpp> + +struct pair_of_ints +{ + pair_of_ints(int first_=0,int second_=0):first(first_),second(second_){} + + bool operator==(const pair_of_ints& x)const + { + return first==x.first&&second==x.second; + } + + bool operator!=(const pair_of_ints& x)const{return !(*this==x);} + + int first,second; +}; + +inline void increment_first(pair_of_ints& p) +{ + ++p.first; +} + +inline void increment_second(pair_of_ints& p) +{ + ++p.second; +} + +inline void increment_int(int& x) +{ + ++x; +} + +inline int decrement_first(pair_of_ints& p) +{ + return --p.first; +} + +inline int decrement_second(pair_of_ints& p) +{ + return --p.second; +} + +inline int decrement_int(int& x) +{ + return --x; +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +namespace boost{ +namespace serialization{ +#endif + +template<class Archive> +void serialize(Archive& ar,pair_of_ints& p,const unsigned int) +{ + ar&boost::serialization::make_nvp("first",p.first); + ar&boost::serialization::make_nvp("second",p.second); +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +} /* namespace serialization */ +} /* namespace boost*/ +#endif + +#endif diff --git a/src/boost/libs/multi_index/test/pre_multi_index.hpp b/src/boost/libs/multi_index/test/pre_multi_index.hpp new file mode 100644 index 000000000..7fc5b9e92 --- /dev/null +++ b/src/boost/libs/multi_index/test/pre_multi_index.hpp @@ -0,0 +1,49 @@ +/* Used in Boost.MultiIndex tests. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#ifndef BOOST_MULTI_INDEX_TEST_PRE_MULTI_INDEX_HPP +#define BOOST_MULTI_INDEX_TEST_PRE_MULTI_INDEX_HPP + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/detail/workaround.hpp> +#include <boost/multi_index/safe_mode_errors.hpp> + +#if defined(__GNUC__)&&defined(__APPLE__)&&\ + (__GNUC__==4)&&(__GNUC_MINOR__==0)&&(__APPLE_CC__<=4061) + /* Darwin 8.1 includes a prerelease version of GCC 4.0 that, alas, + * has a regression as described in + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17435 + * This compiler bug (fixed in the official 4.0 release) ruins the + * mechanisms upon which invariant-checking scope guards are built, + * so we can't set the invariant checking mode. + */ +#else +#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +#endif + +#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE + +#if BOOST_WORKAROUND(__IBMCPP__,<=600) +#pragma info(nolan) /* suppress warnings about offsetof with non-POD types */ +#endif + +struct safe_mode_exception +{ + safe_mode_exception(boost::multi_index::safe_mode::error_code error_code_): + error_code(error_code_) + {} + + boost::multi_index::safe_mode::error_code error_code; +}; + +#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) \ +if(!(expr)){throw safe_mode_exception(error_code);} + +#endif diff --git a/src/boost/libs/multi_index/test/rooted_allocator.hpp b/src/boost/libs/multi_index/test/rooted_allocator.hpp new file mode 100644 index 000000000..dc55c1999 --- /dev/null +++ b/src/boost/libs/multi_index/test/rooted_allocator.hpp @@ -0,0 +1,64 @@ +/* Used in Boost.MultiIndex tests. + * + * Copyright 2003-2020 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/multi_index for library home page. + */ + +#ifndef BOOST_MULTI_INDEX_TEST_ROOTED_ALLOCATOR_HPP +#define BOOST_MULTI_INDEX_TEST_ROOTED_ALLOCATOR_HPP + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/type_traits/integral_constant.hpp> +#include <memory> + +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable:4355) /* this used in base member initializer list */ +#endif + +template<typename T,bool Propagate,bool AlwaysEqual> +class rooted_allocator:public std::allocator<T> +{ + typedef boost::integral_constant<bool,Propagate> propagate_type; + typedef boost::integral_constant<bool,AlwaysEqual> always_equal_type; + +public: + typedef propagate_type propagate_on_container_copy_assignment; + typedef propagate_type propagate_on_container_move_assignment; + typedef propagate_type propagate_on_container_swap; + typedef always_equal_type is_always_equal; + template<typename U> + struct rebind{typedef rooted_allocator<U,Propagate,AlwaysEqual> other;}; + + rooted_allocator():root(0){} + explicit rooted_allocator(int):root(this){} + template<typename U> + rooted_allocator(const rooted_allocator<U,Propagate,AlwaysEqual>& x): + root(x.root){} + + template<typename U> + bool operator==(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const + {return AlwaysEqual?true:root==x.root;} + template<typename U> + bool operator!=(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const + {return !(*this==x);} + + template<typename U> + bool comes_from(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const + {return root==&x;} + +private: + template<typename,bool,bool> friend class rooted_allocator; + + const void* root; +}; + +#if defined(BOOST_MSVC) +#pragma warning(pop) /* C4355 */ +#endif + +#endif diff --git a/src/boost/libs/multi_index/test/small_allocator.hpp b/src/boost/libs/multi_index/test/small_allocator.hpp new file mode 100644 index 000000000..7d1227b0f --- /dev/null +++ b/src/boost/libs/multi_index/test/small_allocator.hpp @@ -0,0 +1,58 @@ +/* Used in Boost.MultiIndex tests. + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +#ifndef BOOST_MULTI_INDEX_TEST_SMALL_ALLOCATOR_HPP +#define BOOST_MULTI_INDEX_TEST_SMALL_ALLOCATOR_HPP + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ + +template<typename T> +class small_allocator +{ +public: + typedef unsigned char size_type; + typedef signed char difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template<class U>struct rebind{typedef small_allocator<U> other;}; + + small_allocator(){} + small_allocator(const small_allocator<T>&){} + template<class U>small_allocator(const small_allocator<U>&,int=0){} + + pointer allocate(size_type n) + { + return pointer((T*)(new char[n*sizeof(T)])); + } + + void deallocate(pointer p,size_type) + { + delete[](char *)&*p; + } + + size_type max_size()const{return (size_type)(-1);} + + friend bool operator==(const small_allocator&,const small_allocator&) + { + return true; + } + + friend bool operator!=(const small_allocator&,const small_allocator&) + { + return false; + } +}; + +#endif diff --git a/src/boost/libs/multi_index/test/test_all_main.cpp b/src/boost/libs/multi_index/test/test_all_main.cpp new file mode 100644 index 000000000..d4536183f --- /dev/null +++ b/src/boost/libs/multi_index/test/test_all_main.cpp @@ -0,0 +1,65 @@ +/* Boost.MultiIndex test suite. + * + * Copyright 2003-2020 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_alloc_awareness.hpp" +#include "test_basic.hpp" +#include "test_capacity.hpp" +#include "test_comparison.hpp" +#include "test_composite_key.hpp" +#include "test_conv_iterators.hpp" +#include "test_copy_assignment.hpp" +#include "test_hash_ops.hpp" +#include "test_iterators.hpp" +#include "test_key.hpp" +#include "test_key_extractors.hpp" +#include "test_list_ops.hpp" +#include "test_modifiers.hpp" +#include "test_mpl_ops.hpp" +#include "test_observers.hpp" +#include "test_projection.hpp" +#include "test_range.hpp" +#include "test_rank_ops.hpp" +#include "test_rearrange.hpp" +#include "test_safe_mode.hpp" +#include "test_serialization.hpp" +#include "test_set_ops.hpp" +#include "test_special_set_ops.hpp" +#include "test_update.hpp" + +int main() +{ + test_allocator_awareness(); + test_basic(); + test_capacity(); + test_comparison(); + test_composite_key(); + test_conv_iterators(); + test_copy_assignment(); + test_hash_ops(); + test_iterators(); + test_key(); + test_key_extractors(); + test_list_ops(); + test_modifiers(); + test_mpl_ops(); + test_observers(); + test_projection(); + test_range(); + test_rank_ops(); + test_rearrange(); + test_safe_mode(); + test_serialization(); + test_set_ops(); + test_special_set_ops(); + test_update(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_alloc_awareness.cpp b/src/boost/libs/multi_index/test/test_alloc_awareness.cpp new file mode 100644 index 000000000..af6075104 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_alloc_awareness.cpp @@ -0,0 +1,159 @@ +/* Boost.MultiIndex test for allocator awareness. + * + * Copyright 2003-2020 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/multi_index for library home page. + */ + +#include "test_alloc_awareness.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/detail/lightweight_test.hpp> +#include <boost/move/core.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/random_access_index.hpp> +#include <boost/multi_index/ranked_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include "rooted_allocator.hpp" + +struct move_tracker +{ + move_tracker(int n):n(n),move_cted(false){} + move_tracker(const move_tracker& x):n(x.n),move_cted(false){} + move_tracker(BOOST_RV_REF(move_tracker) x):n(x.n),move_cted(true){} + move_tracker& operator=(BOOST_COPY_ASSIGN_REF(move_tracker) x) + {n=x.n;return *this;} + move_tracker& operator=(BOOST_RV_REF(move_tracker) x){n=x.n;return *this;} + + int n; + bool move_cted; + +private: + BOOST_COPYABLE_AND_MOVABLE(move_tracker) +}; + +inline bool operator==(const move_tracker& x,const move_tracker& y) +{ + return x.n==y.n; +} + +inline bool operator<(const move_tracker& x,const move_tracker& y) +{ + return x.n<y.n; +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +namespace boost{ +#endif + +inline std::size_t hash_value(const move_tracker& x) +{ + boost::hash<int> h; + return h(x.n); +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +} /* namespace boost */ +#endif + +#if defined(BOOST_NO_CXX17_IF_CONSTEXPR)&&defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable:4127) /* conditional expression is constant */ +#endif + +template<bool Propagate,bool AlwaysEqual> +void test_allocator_awareness_for() +{ + using namespace boost::multi_index; + + typedef rooted_allocator<move_tracker,Propagate,AlwaysEqual> allocator; + typedef multi_index_container< + move_tracker, + indexed_by< + hashed_unique<identity<move_tracker> >, + ordered_unique<identity<move_tracker> >, + random_access<>, + ranked_unique<identity<move_tracker> >, + sequenced<> + >, + allocator + > container; + + allocator root1(0),root2(0); + container c(root1); + for(int i=0;i<10;++i)c.emplace(i); + + BOOST_TEST(c.get_allocator().comes_from(root1)); + + { + container c2(c,root2); + BOOST_TEST(c2.get_allocator().comes_from(root2)); + BOOST_TEST(c2==c); + } + { + container c2(c); + const move_tracker* pfirst=&*c2.begin(); + container c3(boost::move(c2),root2); + BOOST_TEST(c3.get_allocator().comes_from(root2)); + BOOST_TEST(c3==c); + BOOST_TEST(c2.empty()); + BOOST_TEST(AlwaysEqual==(&*c3.begin()==pfirst)); + BOOST_TEST(!AlwaysEqual==(c3.begin()->move_cted)); + } + { + container c2(root2); + c2=c; + BOOST_TEST(c2.get_allocator().comes_from(Propagate?root1:root2)); + BOOST_TEST(c2==c); + } + { + const bool element_transfer=Propagate||AlwaysEqual; + + container c2(c); + const move_tracker* pfirst=&*c2.begin(); + container c3(root2); + c3=boost::move(c2); + BOOST_TEST(c3.get_allocator().comes_from(Propagate?root1:root2)); + BOOST_TEST(c3==c); + BOOST_TEST(c2.empty()); + BOOST_TEST(element_transfer==(&*c3.begin()==pfirst)); + BOOST_TEST(!element_transfer==(c3.begin()->move_cted)); + } + if(Propagate||AlwaysEqual){ + container c2(c); + const move_tracker* pfirst=&*c2.begin(); + container c3(root2); + c3.swap(c2); + BOOST_TEST(c2.get_allocator().comes_from(Propagate?root2:root1)); + BOOST_TEST(c3.get_allocator().comes_from(Propagate?root1:root2)); + BOOST_TEST(c3==c); + BOOST_TEST(c2.empty()); + BOOST_TEST(&*c3.begin()==pfirst); + BOOST_TEST(!c3.begin()->move_cted); + } +} + +#if defined(BOOST_NO_CXX17_IF_CONSTEXPR)&&defined(BOOST_MSVC) +#pragma warning(pop) /* C4127 */ +#endif + +void test_allocator_awareness() +{ + test_allocator_awareness_for<false,false>(); + test_allocator_awareness_for<false,true>(); + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + /* only in C+11 onwards are allocators potentially expected to propagate */ + + test_allocator_awareness_for<true,false>(); + test_allocator_awareness_for<true,true>(); + +#endif +} diff --git a/src/boost/libs/multi_index/test/test_alloc_awareness.hpp b/src/boost/libs/multi_index/test/test_alloc_awareness.hpp new file mode 100644 index 000000000..d659ef55f --- /dev/null +++ b/src/boost/libs/multi_index/test/test_alloc_awareness.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for allocator awareness. + * + * Copyright 2003-2020 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/multi_index for library home page. + */ + +void test_allocator_awareness(); diff --git a/src/boost/libs/multi_index/test/test_alloc_awareness_main.cpp b/src/boost/libs/multi_index/test/test_alloc_awareness_main.cpp new file mode 100644 index 000000000..8fed7f9c9 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_alloc_awareness_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for allocator awareness. + * + * Copyright 2003-2020 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_alloc_awareness.hpp" + +int main() +{ + test_allocator_awareness(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_basic.cpp b/src/boost/libs/multi_index/test/test_basic.cpp new file mode 100644 index 000000000..dbfa9dada --- /dev/null +++ b/src/boost/libs/multi_index/test/test_basic.cpp @@ -0,0 +1,158 @@ +/* Boost.MultiIndex basic test. + * + * Copyright 2003-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/multi_index for library home page. + */ + +#include "test_basic.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <vector> +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +struct less_by_employee_age +{ + bool operator()(const employee& e1,const employee& e2)const + { + return e1.age<e2.age; + } +}; + +struct no_addressof_type +{ + no_addressof_type(int n):n(n){} + + void operator&()const{} + + int n; +}; + +bool operator==(const no_addressof_type& x,const no_addressof_type& y) +{ + return x.n==y.n; +} + +bool operator<(const no_addressof_type& x,const no_addressof_type& y) +{ + return x.n<y.n; +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +namespace boost{ +#endif + +inline std::size_t hash_value(const no_addressof_type& x) +{ + boost::hash<int> h; + return h(x.n); +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +} /* namespace boost */ +#endif + +void test_basic() +{ + employee_set es; + std::vector<employee> v; + +#if defined(BOOST_NO_MEMBER_TEMPLATES) + employee_set_by_name& i1=get<by_name>(es); +#else + employee_set_by_name& i1=es.get<by_name>(); +#endif + + const employee_set_by_age& i2=get<2>(es); + employee_set_as_inserted& i3=get<3>(es); + employee_set_by_ssn& i4=get<ssn>(es); + employee_set_randomly& i5=get<randomly>(es); + + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(5,"Anna",41,1123)); /* clash*/ + i1.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + i3.push_back(employee(3,"Albert",20,9012)); + i4.insert(employee(4,"John",57,1002)); + i5.push_back(employee(0,"Andrew",60,2302)); /* clash */ + + v.push_back(employee(0,"Joe",31,1123)); + v.push_back(employee(1,"Robert",27,5601)); + v.push_back(employee(2,"John",40,7889)); + v.push_back(employee(3,"Albert",20,9012)); + v.push_back(employee(4,"John",57,1002)); + + { + /* by insertion order */ + + BOOST_TEST(std::equal(i3.begin(),i3.end(),v.begin())); + BOOST_TEST(std::equal(i5.begin(),i5.end(),v.begin())); + } + + { + /* by id */ + + std::sort(v.begin(),v.end()); + BOOST_TEST(std::equal(es.begin(),es.end(),v.begin())); + } + + { + /* by age */ + + std::sort(v.begin(),v.end(),less_by_employee_age()); + BOOST_TEST(std::equal(i2.begin(),i2.end(),v.begin())); + } + + { + /* testcase for https://svn.boost.org/trac10/ticket/13307 */ + + typedef multi_index_container< + no_addressof_type, + indexed_by< + random_access<>, + ordered_non_unique<identity<no_addressof_type> >, + sequenced<>, + hashed_non_unique<identity<no_addressof_type> > + > + > multi_index_t; + + multi_index_t c; + const multi_index_t& cc=c; + no_addressof_type x(0); + int a[]={1,2}; + int b[]={6,7}; + c.push_back(x); + c.insert(c.end(),a,a+2); + c.push_back(no_addressof_type(3)); + c.emplace_back(4); + c.get<1>().emplace_hint(c.get<1>().begin(),5); + c.get<1>().insert(b,b+2); + (void)c.begin()->n; + (void)c.get<1>().begin()->n; + (void)c.get<2>().begin()->n; + (void)c.get<3>().begin()->n; + (void)c.get<3>().begin(0)->n; + (void)c.iterator_to(c.front()); + (void)cc.iterator_to(c.front()); + (void)c.get<1>().iterator_to(c.front()); + (void)cc.get<1>().iterator_to(c.front()); + (void)c.get<2>().iterator_to(c.front()); + (void)cc.get<2>().iterator_to(c.front()); + (void)c.get<3>().iterator_to(c.front()); + (void)cc.get<3>().iterator_to(c.front()); + (void)c.get<3>().local_iterator_to(c.front()); + (void)cc.get<3>().local_iterator_to(c.front()); + multi_index_t c2=c;(void)c2; + c.erase(c.begin()); + c.erase(c.begin(),c.end()); + } + +} diff --git a/src/boost/libs/multi_index/test/test_basic.hpp b/src/boost/libs/multi_index/test/test_basic.hpp new file mode 100644 index 000000000..652c0e090 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_basic.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex basic test. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_basic(); diff --git a/src/boost/libs/multi_index/test/test_basic_main.cpp b/src/boost/libs/multi_index/test/test_basic_main.cpp new file mode 100644 index 000000000..a98132ac3 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_basic_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex basic test. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_basic.hpp" + +int main() +{ + test_basic(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_capacity.cpp b/src/boost/libs/multi_index/test/test_capacity.cpp new file mode 100644 index 000000000..57774da8d --- /dev/null +++ b/src/boost/libs/multi_index/test/test_capacity.cpp @@ -0,0 +1,97 @@ +/* Boost.MultiIndex test for capacity memfuns. + * + * Copyright 2003-2015 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/multi_index for library home page. + */ + +#include "test_capacity.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +void test_capacity() +{ + employee_set es; + + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + es.insert(employee(3,"Albert",20,9012)); + es.insert(employee(4,"John",57,1002)); + + BOOST_TEST(!es.empty()); + BOOST_TEST(es.size()==5); + BOOST_TEST(es.size()<=es.max_size()); + + es.erase(es.begin()); + BOOST_TEST(!get<name>(es).empty()); + BOOST_TEST(get<name>(es).size()==4); + BOOST_TEST(get<name>(es).size()<=get<name>(es).max_size()); + + es.erase(es.begin()); + BOOST_TEST(!get<as_inserted>(es).empty()); + BOOST_TEST(get<as_inserted>(es).size()==3); + BOOST_TEST(get<as_inserted>(es).size()<=get<as_inserted>(es).max_size()); + + multi_index_container<int,indexed_by<sequenced<> > > ss; + + ss.resize(10); + BOOST_TEST(ss.size()==10); + BOOST_TEST(ss.size()<=ss.max_size()); + + ss.resize(20,666); + BOOST_TEST(ss.size()==20); + BOOST_TEST(ss.back()==666); + + ss.resize(5,10); + BOOST_TEST(ss.size()==5); + + ss.resize(4); + BOOST_TEST(ss.size()==4); + + multi_index_container<int,indexed_by<random_access<> > > rs; + + rs.resize(10); + BOOST_TEST(rs.size()==10); + BOOST_TEST(rs.size()<=rs.max_size()); + BOOST_TEST(rs.size()<=rs.capacity()); + + rs.resize(20,666); + BOOST_TEST(rs.size()==20); + BOOST_TEST(rs.back()==666); + BOOST_TEST(rs.size()<=rs.capacity()); + + employee_set::size_type c=rs.capacity(); + rs.resize(10,20); + BOOST_TEST(rs.size()==10); + BOOST_TEST(rs.capacity()==c); + + rs.resize(5); + BOOST_TEST(rs.size()==5); + BOOST_TEST(rs.capacity()==c); + + rs.reserve(100); + BOOST_TEST(rs.size()==5); + BOOST_TEST(rs.capacity()>=100); + + c=rs.capacity(); + rs.reserve(99); + BOOST_TEST(rs.size()==5); + BOOST_TEST(rs.capacity()==c); + + rs.shrink_to_fit(); + BOOST_TEST(rs.size()==5); + BOOST_TEST(rs.capacity()==rs.size()); + + rs.clear(); + rs.shrink_to_fit(); + BOOST_TEST(rs.capacity()==0); +} diff --git a/src/boost/libs/multi_index/test/test_capacity.hpp b/src/boost/libs/multi_index/test/test_capacity.hpp new file mode 100644 index 000000000..73bcf5e93 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_capacity.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for capacity memfuns. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_capacity(); diff --git a/src/boost/libs/multi_index/test/test_capacity_main.cpp b/src/boost/libs/multi_index/test/test_capacity_main.cpp new file mode 100644 index 000000000..ff8024280 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_capacity_main.cpp @@ -0,0 +1,19 @@ +/* Boost.MultiIndex test for capacity memfuns. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_capacity.hpp" + +int main() +{ + test_capacity(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/multi_index/test/test_comparison.cpp b/src/boost/libs/multi_index/test/test_comparison.cpp new file mode 100644 index 000000000..15226196b --- /dev/null +++ b/src/boost/libs/multi_index/test/test_comparison.cpp @@ -0,0 +1,151 @@ +/* Boost.MultiIndex test for comparison functions. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include "test_comparison.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include "pair_of_ints.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +template<typename Value> +struct lookup_list{ + typedef multi_index_container< + Value, + indexed_by< + sequenced<>, + ordered_non_unique<identity<Value> > + > + > type; +}; + +template<typename Value> +struct lookup_vector{ + typedef multi_index_container< + Value, + indexed_by< + random_access<>, + ordered_non_unique<identity<Value> > + > + > type; +}; + +void test_comparison() +{ + employee_set es; + employee_set_by_name& i1=get<1>(es); + employee_set_by_age& i2=get<2>(es); + employee_set_as_inserted& i3=get<3>(es); + employee_set_by_ssn& i4=get<4>(es); + employee_set_randomly& i5=get<5>(es); + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + es.insert(employee(3,"Albert",20,9012)); + es.insert(employee(4,"John",57,1002)); + + employee_set es2; + employee_set_by_name& i12=get<by_name>(es2); + employee_set_by_age& i22=get<age>(es2); + employee_set_as_inserted& i32=get<3>(es2); + employee_set_by_ssn& i42=get<4>(es2); + employee_set_randomly& i52=get<5>(es2); + es2.insert(employee(0,"Joe",31,1123)); + es2.insert(employee(1,"Robert",27,5601)); + es2.insert(employee(2,"John",40,7889)); + es2.insert(employee(3,"Albert",20,9012)); + + BOOST_TEST(es==es&&es<=es&&es>=es&& + i12==i12&& + i22==i22&&i22<=i22&&i22>=i22&& + i32==i32&&i32<=i32&&i32>=i32&& + i42==i42&& + i52==i52&&i52<=i52&&i52>=i52); + BOOST_TEST(es!=es2&&es2<es&&es>es2&&!(es<=es2)&&!(es2>=es)); + BOOST_TEST(i1!=i12); + BOOST_TEST(i2!=i22&&i22<i2&&i2>i22&&!(i2<=i22)&&!(i22>=i2)); + BOOST_TEST(i3!=i32&&i32<i3&&i3>i32&&!(i3<=i32)&&!(i32>=i3)); + BOOST_TEST(i4!=i42); + BOOST_TEST(i5!=i52&&i52<i5&&i5>i52&&!(i5<=i52)&&!(i52>=i5)); + + multi_index_container< + pair_of_ints, + indexed_by< + hashed_non_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)> + > + > hc1,hc2; + hc1.insert(pair_of_ints(0,0)); + hc1.insert(pair_of_ints(0,1)); + hc1.insert(pair_of_ints(0,2)); + hc1.insert(pair_of_ints(0,3)); + hc1.insert(pair_of_ints(1,0)); + hc1.insert(pair_of_ints(1,1)); + + hc2.insert(pair_of_ints(0,2)); + hc2.insert(pair_of_ints(0,1)); + hc2.insert(pair_of_ints(1,1)); + hc2.insert(pair_of_ints(1,0)); + hc2.insert(pair_of_ints(0,3)); + hc2.insert(pair_of_ints(0,0)); + BOOST_TEST(hc1==hc2); + + hc1.insert(pair_of_ints(0,4)); + hc2.insert(pair_of_ints(0,5)); + BOOST_TEST(hc1!=hc2); + + lookup_list<int>::type l1; + lookup_list<char>::type l2; + lookup_vector<char>::type l3; + lookup_list<long>::type l4; + lookup_vector<long>::type l5; + + l1.push_back(3); + l1.push_back(4); + l1.push_back(5); + l1.push_back(1); + l1.push_back(2); + + l2.push_back(char(3)); + l2.push_back(char(4)); + l2.push_back(char(5)); + l2.push_back(char(1)); + l2.push_back(char(2)); + + l3.push_back(char(3)); + l3.push_back(char(4)); + l3.push_back(char(5)); + l3.push_back(char(1)); + l3.push_back(char(2)); + + l4.push_back(long(3)); + l4.push_back(long(4)); + l4.push_back(long(5)); + l4.push_back(long(1)); + + l5.push_back(long(3)); + l5.push_back(long(4)); + l5.push_back(long(5)); + l5.push_back(long(1)); + + BOOST_TEST(l1==l2&&l1<=l2&&l1>=l2); + BOOST_TEST( + get<1>(l1)==get<1>(l2)&&get<1>(l1)<=get<1>(l2)&&get<1>(l1)>=get<1>(l2)); + BOOST_TEST( + get<1>(l1)==get<1>(l3)&&get<1>(l1)<=get<1>(l3)&&get<1>(l1)>=get<1>(l3)); + BOOST_TEST(l1!=l4&&l4<l1&&l1>l4); + BOOST_TEST( + get<1>(l1)!=get<1>(l4)&&get<1>(l1)<get<1>(l4)&&get<1>(l4)>get<1>(l1)); + BOOST_TEST(l3!=l5&&l5<l3&&l3>l5); + BOOST_TEST( + get<1>(l3)!=get<1>(l5)&&get<1>(l3)<get<1>(l5)&&get<1>(l5)>get<1>(l3)); +} diff --git a/src/boost/libs/multi_index/test/test_comparison.hpp b/src/boost/libs/multi_index/test/test_comparison.hpp new file mode 100644 index 000000000..4f0106922 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_comparison.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for comparison functions. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_comparison(); diff --git a/src/boost/libs/multi_index/test/test_comparison_main.cpp b/src/boost/libs/multi_index/test/test_comparison_main.cpp new file mode 100644 index 000000000..aace1229e --- /dev/null +++ b/src/boost/libs/multi_index/test/test_comparison_main.cpp @@ -0,0 +1,19 @@ +/* Boost.MultiIndex test for comparison functions. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_comparison.hpp" + +int main() +{ + test_comparison(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/multi_index/test/test_composite_key.cpp b/src/boost/libs/multi_index/test/test_composite_key.cpp new file mode 100644 index 000000000..24049692a --- /dev/null +++ b/src/boost/libs/multi_index/test/test_composite_key.cpp @@ -0,0 +1,670 @@ +/* Boost.MultiIndex test for composite_key. + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +#include "test_composite_key.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/detail/lightweight_test.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/composite_key.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> + +using namespace boost::multi_index; +using namespace boost::tuples; + +struct is_composite_key_result_helper +{ + typedef char yes; + struct no{char m[2];}; + + static no test(void*); + + template<typename CompositeKey> + static yes test(composite_key_result<CompositeKey>*); +}; + +template<typename T> +struct is_composite_key_result +{ + typedef is_composite_key_result_helper helper; + + BOOST_STATIC_CONSTANT(bool, + value=( + sizeof(helper::test((T*)0))== + sizeof(typename helper::yes))); +}; + +template<typename CompositeKeyResult> +struct composite_key_result_length +{ + BOOST_STATIC_CONSTANT(int, + value=boost::tuples::length< + BOOST_DEDUCED_TYPENAME + CompositeKeyResult::composite_key_type::key_extractor_tuple + >::value); +}; + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +struct is_boost_tuple_helper +{ + typedef char yes; + struct no{char m[2];}; + + static no test(void*); + + template<BOOST_PP_ENUM_PARAMS(10,typename T)> + static yes test(boost::tuple<BOOST_PP_ENUM_PARAMS(10,T)>*); +}; + +template<typename T> +struct is_boost_tuple +{ + typedef is_boost_tuple_helper helper; + + BOOST_STATIC_CONSTANT(bool, + value=( + sizeof(helper::test((T*)0))== + sizeof(typename helper::yes))); +}; + +template<typename T> +struct composite_object_length +{ + typedef typename boost::mpl::if_c< + is_composite_key_result<T>::value, + composite_key_result_length<T>, + typename boost::mpl::if_c< + is_boost_tuple<T>::value, + boost::tuples::length<T>, + std::tuple_size<T> + >::type + >::type type; + + BOOST_STATIC_CONSTANT(int,value=type::value); +}; +#else +template<typename T> +struct composite_object_length +{ + typedef typename boost::mpl::if_c< + is_composite_key_result<T>::value, + composite_key_result_length<T>, + boost::tuples::length<T> + >::type type; + + BOOST_STATIC_CONSTANT(int,value=type::value); +}; +#endif + +template<typename CompositeKeyResult,typename T2> +struct comparison_equal_length +{ + static bool is_less(const CompositeKeyResult& x,const T2& y) + { + composite_key_result_equal_to<CompositeKeyResult> eq; + composite_key_result_less<CompositeKeyResult> lt; + composite_key_result_greater<CompositeKeyResult> gt; + std::equal_to<CompositeKeyResult> std_eq; + std::less<CompositeKeyResult> std_lt; + std::greater<CompositeKeyResult> std_gt; + + return (x< y) && !(y< x)&& + !(x==y) && !(y==x)&& + (x!=y) && (y!=x)&& + !(x> y) && (y> x)&& + !(x>=y) && (y>=x)&& + (x<=y) && !(y<=x)&& + !eq(x,y) && !eq(y,x)&& + lt(x,y) && !lt(y,x)&& + !gt(x,y) && gt(y,x)&& + !std_eq(x,y) && !std_eq(y,x)&& + std_lt(x,y) && !std_lt(y,x)&& + !std_gt(x,y) && std_gt(y,x); + } + + static bool is_greater(const CompositeKeyResult& x,const T2& y) + { + composite_key_result_equal_to<CompositeKeyResult> eq; + composite_key_result_less<CompositeKeyResult> lt; + composite_key_result_greater<CompositeKeyResult> gt; + std::equal_to<CompositeKeyResult> std_eq; + std::less<CompositeKeyResult> std_lt; + std::greater<CompositeKeyResult> std_gt; + + return !(x< y) && (y< x)&& + !(x==y) && !(y==x)&& + (x!=y) && (y!=x)&& + (x> y) && !(y> x)&& + (x>=y) && !(y>=x)&& + !(x<=y) && (y<=x)&& + !eq(x,y) && !eq(y,x)&& + !lt(x,y) && lt(y,x)&& + gt(x,y) && !gt(y,x)&& + !std_eq(x,y) && !std_eq(y,x)&& + !std_lt(x,y) && std_lt(y,x)&& + std_gt(x,y) && !std_gt(y,x); + } + + static bool is_equiv(const CompositeKeyResult& x,const T2& y) + { + composite_key_result_equal_to<CompositeKeyResult> eq; + composite_key_result_less<CompositeKeyResult> lt; + composite_key_result_greater<CompositeKeyResult> gt; + std::equal_to<CompositeKeyResult> std_eq; + std::less<CompositeKeyResult> std_lt; + std::greater<CompositeKeyResult> std_gt; + + return !(x< y) && !(y< x)&& + (x==y) && (y==x)&& + !(x!=y) && !(y!=x)&& + !(x> y) && !(y> x)&& + (x>=y) && (y>=x)&& + (x<=y) && (y<=x)&& + eq(x,y) && eq(y,x)&& + !lt(x,y) && !lt(y,x)&& + !gt(x,y) && !gt(y,x)&& + std_eq(x,y) && std_eq(y,x)&& + !std_lt(x,y) && !std_lt(y,x)&& + !std_gt(x,y) && !std_gt(y,x); + } +}; + +template<typename CompositeKeyResult,typename T2> +struct comparison_different_length +{ + static bool is_less(const CompositeKeyResult& x,const T2& y) + { + composite_key_result_less<CompositeKeyResult> lt; + composite_key_result_greater<CompositeKeyResult> gt; + std::less<CompositeKeyResult> std_lt; + std::greater<CompositeKeyResult> std_gt; + + return (x< y) && !(y< x)&& + !(x> y) && (y> x)&& + !(x>=y) && (y>=x)&& + (x<=y) && !(y<=x)&& + lt(x,y) && !lt(y,x)&& + !gt(x,y) && gt(y,x)&& + std_lt(x,y) && !std_lt(y,x)&& + !std_gt(x,y) && std_gt(y,x); + } + + static bool is_greater(const CompositeKeyResult& x,const T2& y) + { + composite_key_result_less<CompositeKeyResult> lt; + composite_key_result_greater<CompositeKeyResult> gt; + std::less<CompositeKeyResult> std_lt; + std::greater<CompositeKeyResult> std_gt; + + return !(x< y) && (y< x)&& + (x> y) && !(y> x)&& + (x>=y) && !(y>=x)&& + !(x<=y) && (y<=x)&& + !lt(x,y) && lt(y,x)&& + gt(x,y) && !gt(y,x)&& + !std_lt(x,y) && std_lt(y,x)&& + std_gt(x,y) && !std_gt(y,x); + } + + static bool is_equiv(const CompositeKeyResult& x,const T2& y) + { + composite_key_result_less<CompositeKeyResult> lt; + composite_key_result_greater<CompositeKeyResult> gt; + std::less<CompositeKeyResult> std_lt; + std::greater<CompositeKeyResult> std_gt; + + return !(x< y) && !(y< x)&& + !(x> y) && !(y> x)&& + (x>=y) && (y>=x)&& + (x<=y) && (y<=x)&& + !lt(x,y) && !lt(y,x)&& + !gt(x,y) && !gt(y,x)&& + !std_lt(x,y) && !std_lt(y,x)&& + !std_gt(x,y) && !std_gt(y,x); + } +}; + +template<typename CompositeKeyResult,typename T2> +struct comparison_helper: + boost::mpl::if_c< + composite_key_result_length<CompositeKeyResult>::value== + composite_object_length<T2>::value, + comparison_equal_length<CompositeKeyResult,T2>, + comparison_different_length<CompositeKeyResult,T2> + >::type +{ +}; + +template<typename CompositeKeyResult,typename T2> +static bool is_less(const CompositeKeyResult& x,const T2& y) +{ + return comparison_helper<CompositeKeyResult,T2>::is_less(x,y); +} + +template<typename CompositeKeyResult,typename T2> +static bool is_greater(const CompositeKeyResult& x,const T2& y) +{ + return comparison_helper<CompositeKeyResult,T2>::is_greater(x,y); +} + +template<typename CompositeKeyResult,typename T2> +static bool is_equiv(const CompositeKeyResult& x,const T2& y) +{ + return comparison_helper<CompositeKeyResult,T2>::is_equiv(x,y); +} + +template<typename T1,typename T2,typename Compare> +static bool is_less(const T1& x,const T2& y,const Compare& c) +{ + return c(x,y)&&!c(y,x); +} + +template<typename T1,typename T2,typename Compare> +static bool is_greater(const T1& x,const T2& y,const Compare& c) +{ + return c(y,x)&&!c(x,y); +} + +template<typename T1,typename T2,typename Compare> +static bool is_equiv(const T1& x,const T2& y,const Compare& c) +{ + return !c(x,y)&&!c(y,x); +} + +template<typename T1,typename T2,typename Compare,typename Equiv> +static bool is_less( + const T1& x,const T2& y,const Compare& c,const Equiv& eq) +{ + return c(x,y)&&!c(y,x)&&!eq(x,y)&&!eq(y,x); +} + +template<typename T1,typename T2,typename Compare,typename Equiv> +static bool is_greater( + const T1& x,const T2& y,const Compare& c,const Equiv& eq) +{ + return c(y,x)&&!c(x,y)&&!eq(x,y)&&!eq(y,x); +} + +template<typename T1,typename T2,typename Compare,typename Equiv> +static bool is_equiv( + const T1& x,const T2& y,const Compare& c,const Equiv& eq) +{ + return !c(x,y)&&!c(y,x)&&eq(x,y)&&eq(y,x); +} + +struct xyz +{ + xyz(int x_=0,int y_=0,int z_=0):x(x_),y(y_),z(z_){} + + int x; + int y; + int z; +}; + +struct modulo_equal +{ + modulo_equal(int i):i_(i){} + bool operator ()(int x,int y)const{return (x%i_)==(y%i_);} + +private: + int i_; +}; + +struct xystr +{ + xystr(int x_=0,int y_=0,std::string str_=0):x(x_),y(y_),str(str_){} + + int x; + int y; + std::string str; +}; + +#define TUPLE_MAKER_CREATE(z,n,tuple) \ +template<BOOST_PP_ENUM_PARAMS(n,typename T)> \ +static tuple<BOOST_PP_ENUM_PARAMS(n,T)> \ +create(BOOST_PP_ENUM_BINARY_PARAMS(n,const T,& t)){ \ + return tuple<BOOST_PP_ENUM_PARAMS(n,T)>( \ + BOOST_PP_ENUM_PARAMS(n,t)); \ +} + +#define DEFINE_TUPLE_MAKER(name,tuple) \ +struct name \ +{ \ + static tuple<> create(){return tuple<>();} \ + BOOST_PP_REPEAT_FROM_TO(1,5,TUPLE_MAKER_CREATE,tuple) \ +}; + +DEFINE_TUPLE_MAKER(boost_tuple_maker,boost::tuple) + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +DEFINE_TUPLE_MAKER(std_tuple_maker,std::tuple) +#endif + +#undef DEFINE_TUPLE_MAKER +#undef TUPLE_MAKER_CREATE + +template<typename TupleMaker> +void test_composite_key_template() +{ + typedef composite_key< + xyz, + BOOST_MULTI_INDEX_MEMBER(xyz,int,x), + BOOST_MULTI_INDEX_MEMBER(xyz,int,y), + BOOST_MULTI_INDEX_MEMBER(xyz,int,z) + > ckey_t1; + + typedef multi_index_container< + xyz, + indexed_by< + ordered_unique<ckey_t1> + > + > indexed_t1; + + indexed_t1 mc1; + mc1.insert(xyz(0,0,0)); + mc1.insert(xyz(0,0,1)); + mc1.insert(xyz(0,1,0)); + mc1.insert(xyz(0,1,1)); + mc1.insert(xyz(1,0,0)); + mc1.insert(xyz(1,0,1)); + mc1.insert(xyz(1,1,0)); + mc1.insert(xyz(1,1,1)); + + BOOST_TEST(mc1.size()==8); + BOOST_TEST( + std::distance( + mc1.find(mc1.key_extractor()(xyz(0,0,0))), + mc1.find(mc1.key_extractor()(xyz(1,0,0))))==4); + BOOST_TEST( + std::distance( + mc1.find(TupleMaker::create(0,0,0)), + mc1.find(TupleMaker::create(1,0,0)))==4); + BOOST_TEST( + std::distance( + mc1.lower_bound(TupleMaker::create(0,0)), + mc1.upper_bound(TupleMaker::create(1,0)))==6); + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + BOOST_TEST( + std::distance( + mc1.lower_bound(1), + mc1.upper_bound(1))==4); +#endif + + ckey_t1 ck1; + ckey_t1 ck2(ck1); + ckey_t1 ck3( + boost::make_tuple( + BOOST_MULTI_INDEX_MEMBER(xyz,int,x)(), + BOOST_MULTI_INDEX_MEMBER(xyz,int,y)(), + BOOST_MULTI_INDEX_MEMBER(xyz,int,z)())); + ckey_t1 ck4(get<0>(ck1.key_extractors())); + + (void)ck3; /* prevent unused var */ + + get<2>(ck4.key_extractors())= + get<2>(ck2.key_extractors()); + + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)))); + BOOST_TEST(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0)))); + BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)))); + + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0))); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(1))); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1))); + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0))); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,1))); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,-1))); + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0))); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1))); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1))); + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0,1))); + + typedef composite_key_result_less<ckey_t1::result_type> ckey_comp_t1; + typedef composite_key_result_equal_to<ckey_t1::result_type> ckey_eq_t1; + + ckey_comp_t1 cp1; + ckey_eq_t1 eq1; + + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp1,eq1)); + BOOST_TEST(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp1,eq1)); + BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp1,eq1)); + + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0),cp1)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(1),cp1)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1),cp1)); + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),0,cp1)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),1,cp1)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),-1,cp1)); +#endif + + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp1)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp1)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp1)); + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp1,eq1)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp1,eq1)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp1,eq1)); + + typedef composite_key_result_greater<ckey_t1::result_type> ckey_comp_t2; + + ckey_comp_t2 cp2; + + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp2)); + BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp2)); + BOOST_TEST(is_less (ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp2)); + + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0),cp2)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(1),cp2)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(-1),cp2)); + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp2)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp2)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp2)); + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp2)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp2)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp2)); + + typedef composite_key_equal_to< + modulo_equal, + modulo_equal, + std::equal_to<int>, + std::equal_to<int> + > ckey_eq_t2; + + ckey_eq_t2 eq2( + boost::make_tuple( + modulo_equal(2), + modulo_equal(3), + std::equal_to<int>(), + std::equal_to<int>())); + ckey_eq_t2 eq3(eq2); + ckey_eq_t2 eq4( + get<0>(eq3.key_eqs()), + get<1>(eq3.key_eqs())); + + eq3=eq4; /* prevent unused var */ + eq4=eq3; /* prevent unused var */ + + BOOST_TEST( eq2(ck1(xyz(0,0,0)),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(0,1,0)),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(0,2,0)),ck1(xyz(0,0,0)))); + BOOST_TEST( eq2(ck1(xyz(0,3,0)),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(1,0,0)),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(1,1,0)),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(1,2,0)),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(1,3,0)),ck1(xyz(0,0,0)))); + BOOST_TEST( eq2(ck1(xyz(2,0,0)),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(2,1,0)),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(2,2,0)),ck1(xyz(0,0,0)))); + BOOST_TEST( eq2(ck1(xyz(2,3,0)),ck1(xyz(0,0,0)))); + + BOOST_TEST( eq2(TupleMaker::create(0,0,0),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(0,1,0)) ,TupleMaker::create(0,0,0))); + BOOST_TEST(!eq2(TupleMaker::create(0,2,0),ck1(xyz(0,0,0)))); + BOOST_TEST( eq2(ck1(xyz(0,3,0)) ,TupleMaker::create(0,0,0))); + BOOST_TEST(!eq2(TupleMaker::create(1,0,0),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(1,1,0)) ,TupleMaker::create(0,0,0))); + BOOST_TEST(!eq2(TupleMaker::create(1,2,0),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(1,3,0)) ,TupleMaker::create(0,0,0))); + BOOST_TEST( eq2(TupleMaker::create(2,0,0),ck1(xyz(0,0,0)))); + BOOST_TEST(!eq2(ck1(xyz(2,1,0)) ,TupleMaker::create(0,0,0))); + BOOST_TEST(!eq2(TupleMaker::create(2,2,0),ck1(xyz(0,0,0)))); + BOOST_TEST( eq2(ck1(xyz(2,3,0)) ,TupleMaker::create(0,0,0))); + + typedef composite_key_compare< + std::less<int>, + std::greater<int>, /* order reversed */ + std::less<int> + > ckey_comp_t3; + + ckey_comp_t3 cp3; + ckey_comp_t3 cp4(cp3); + ckey_comp_t3 cp5( + boost::make_tuple( + std::less<int>(), + std::greater<int>(), + std::less<int>())); + ckey_comp_t3 cp6(get<0>(cp3.key_comps())); + + cp4=cp5; /* prevent unused var */ + cp5=cp6; /* prevent unused var */ + cp6=cp4; /* prevent unused var */ + + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),ck2(xyz(0,0,0)),cp3)); + BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,1,0)),cp3)); + BOOST_TEST(is_greater(ck1(xyz(0,0,1)),ck2(xyz(0,0,0)),cp3)); + + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0),cp3)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(1),cp3)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(-1),cp3)); + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0),cp3)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,-1),cp3)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,1),cp3)); + BOOST_TEST(is_equiv (ck1(xyz(0,0,0)),TupleMaker::create(0,0,0),cp3)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),TupleMaker::create(0,0,1),cp3)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),TupleMaker::create(0,0,-1),cp3)); + + typedef composite_key< + xyz, + BOOST_MULTI_INDEX_MEMBER(xyz,int,y), /* members reversed */ + BOOST_MULTI_INDEX_MEMBER(xyz,int,x) + > ckey_t2; + + ckey_t2 ck5; + + BOOST_TEST(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)))); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)))); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)))); + + BOOST_TEST(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp1)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp1)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp1)); + + BOOST_TEST(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp2)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp2)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp2)); + + BOOST_TEST(is_equiv (ck1(xyz(0,0,1)),ck5(xyz(0,0,0)),cp3)); + BOOST_TEST(is_less (ck1(xyz(0,0,0)),ck5(xyz(-1,1,0)),cp3)); + BOOST_TEST(is_greater(ck1(xyz(0,0,0)),ck5(xyz(1,-1,0)),cp3)); + + typedef multi_index_container< + xyz, + indexed_by< + hashed_unique<ckey_t1> + > + > indexed_t2; + + indexed_t2 mc2; + mc2.insert(xyz(0,0,0)); + mc2.insert(xyz(0,0,1)); + mc2.insert(xyz(0,1,0)); + mc2.insert(xyz(0,1,1)); + mc2.insert(xyz(1,0,0)); + mc2.insert(xyz(1,0,1)); + mc2.insert(xyz(1,1,0)); + mc2.insert(xyz(1,1,1)); + mc2.insert(xyz(0,0,0)); + mc2.insert(xyz(0,0,1)); + mc2.insert(xyz(0,1,0)); + mc2.insert(xyz(0,1,1)); + mc2.insert(xyz(1,0,0)); + mc2.insert(xyz(1,0,1)); + mc2.insert(xyz(1,1,0)); + mc2.insert(xyz(1,1,1)); + + BOOST_TEST(mc2.size()==8); + BOOST_TEST(mc2.find(TupleMaker::create(0,0,1))->z==1); + BOOST_TEST(ck1(*(mc2.find(TupleMaker::create(1,0,1))))== + TupleMaker::create(1,0,1)); + + typedef composite_key< + xystr, + BOOST_MULTI_INDEX_MEMBER(xystr,std::string,str), + BOOST_MULTI_INDEX_MEMBER(xystr,int,x), + BOOST_MULTI_INDEX_MEMBER(xystr,int,y) + > ckey_t3; + + ckey_t3 ck6; + + typedef composite_key_hash< + boost::hash<std::string>, + boost::hash<int>, + boost::hash<int> + > ckey_hash_t; + + ckey_hash_t ch1; + ckey_hash_t ch2(ch1); + ckey_hash_t ch3( + boost::make_tuple( + boost::hash<std::string>(), + boost::hash<int>(), + boost::hash<int>())); + ckey_hash_t ch4(get<0>(ch1.key_hash_functions())); + + ch2=ch3; /* prevent unused var */ + ch3=ch4; /* prevent unused var */ + ch4=ch2; /* prevent unused var */ + + BOOST_TEST( + ch1(ck6(xystr(0,0,"hello")))== + ch1(TupleMaker::create(std::string("hello"),0,0))); + BOOST_TEST( + ch1(ck6(xystr(4,5,"world")))== + ch1(TupleMaker::create(std::string("world"),4,5))); + + typedef boost::hash<composite_key_result<ckey_t3> > ckeyres_hash_t; + + ckeyres_hash_t crh; + + BOOST_TEST( + ch1(ck6(xystr(0,0,"hello")))==crh(ck6(xystr(0,0,"hello")))); + BOOST_TEST( + ch1(ck6(xystr(4,5,"world")))==crh(ck6(xystr(4,5,"world")))); +} + +void test_composite_key() +{ + test_composite_key_template<boost_tuple_maker>(); + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE)&&\ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + test_composite_key_template<std_tuple_maker>(); +#endif +} diff --git a/src/boost/libs/multi_index/test/test_composite_key.hpp b/src/boost/libs/multi_index/test/test_composite_key.hpp new file mode 100644 index 000000000..8a7ae5344 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_composite_key.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for composite_key. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_composite_key(); diff --git a/src/boost/libs/multi_index/test/test_composite_key_main.cpp b/src/boost/libs/multi_index/test/test_composite_key_main.cpp new file mode 100644 index 000000000..79f7c2d4e --- /dev/null +++ b/src/boost/libs/multi_index/test/test_composite_key_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for composite_key. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_composite_key.hpp" + +int main() +{ + test_composite_key(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_conv_iterators.cpp b/src/boost/libs/multi_index/test/test_conv_iterators.cpp new file mode 100644 index 000000000..24751e011 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_conv_iterators.cpp @@ -0,0 +1,75 @@ +/* Boost.MultiIndex test for interconvertibilty between const and + * non-const iterators. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include "test_conv_iterators.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +void test_conv_iterators() +{ + employee_set es; + es.insert(employee(2,"John",40,7889)); + + { + const employee_set& ces=es; + employee_set::iterator it=es.find(employee(2,"John",40,7889)); + employee_set::const_iterator it1=es.find(employee(2,"John",40,7889)); + employee_set::const_iterator it2=ces.find(employee(2,"John",40,7889)); + + BOOST_TEST(it==it1&&it1==it2&&it2==it); + BOOST_TEST(*it==*it1&&*it1==*it2&&*it2==*it); + } + { + employee_set_by_name& i1=get<1>(es); + const employee_set_by_name& ci1=get<1>(es); + employee_set_by_name::iterator it=i1.find("John"); + employee_set_by_name::const_iterator it1=i1.find("John"); + employee_set_by_name::const_iterator it2=ci1.find("John"); + + BOOST_TEST(it==it1&&it1==it2&&it2==it); + BOOST_TEST(*it==*it1&&*it1==*it2&&*it2==*it); + } + { + employee_set_by_name& i1=get<1>(es); + const employee_set_by_name& ci1=get<1>(es); + employee_set_by_name::local_iterator it=i1.begin(i1.bucket("John")); + employee_set_by_name::const_local_iterator it1=i1.begin(i1.bucket("John")); + employee_set_by_name::const_local_iterator it2=ci1.begin(ci1.bucket("John")); + + BOOST_TEST(it==it1&&it1==it2&&it2==it); + BOOST_TEST(*it==*it1&&*it1==*it2&&*it2==*it); + } + { + employee_set_as_inserted& i3=get<3>(es); + const employee_set_as_inserted& ci3=get<3>(es); + employee_set_as_inserted::iterator it=i3.begin(); + employee_set_as_inserted::const_iterator it1=i3.begin(); + employee_set_as_inserted::const_iterator it2=ci3.begin(); + + BOOST_TEST(it==it1&&it1==it2&&it2==it); + BOOST_TEST(*it==*it1&&*it1==*it2&&*it2==*it); + } + { + employee_set_randomly& i5=get<5>(es); + const employee_set_randomly& ci5=get<5>(es); + employee_set_randomly::iterator it=i5.begin(); + employee_set_randomly::const_iterator it1=i5.begin(); + employee_set_randomly::const_iterator it2=ci5.begin(); + + BOOST_TEST(it==it1&&it1==it2&&it2==it); + BOOST_TEST(*it==*it1&&*it1==*it2&&*it2==*it); + } +} diff --git a/src/boost/libs/multi_index/test/test_conv_iterators.hpp b/src/boost/libs/multi_index/test/test_conv_iterators.hpp new file mode 100644 index 000000000..1e493b52a --- /dev/null +++ b/src/boost/libs/multi_index/test/test_conv_iterators.hpp @@ -0,0 +1,12 @@ +/* Boost.MultiIndex test for interconvertibilty between const and + * non-const iterators. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_conv_iterators(); diff --git a/src/boost/libs/multi_index/test/test_conv_iterators_main.cpp b/src/boost/libs/multi_index/test/test_conv_iterators_main.cpp new file mode 100644 index 000000000..5d07f7fc1 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_conv_iterators_main.cpp @@ -0,0 +1,21 @@ +/* Boost.MultiIndex test for interconvertibilty between const and + * non-const iterators. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_conv_iterators.hpp" + +int main() +{ + test_conv_iterators(); + return boost::report_errors(); +} + + diff --git a/src/boost/libs/multi_index/test/test_copy_assignment.cpp b/src/boost/libs/multi_index/test/test_copy_assignment.cpp new file mode 100644 index 000000000..fca40b267 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_copy_assignment.cpp @@ -0,0 +1,365 @@ +/* Boost.MultiIndex test for copying and assignment. + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +#include "test_copy_assignment.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <boost/move/utility_core.hpp> +#include <list> +#include <numeric> +#include <vector> +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include "small_allocator.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +#if BOOST_WORKAROUND(__MWERKS__,<=0x3003) +/* The "ISO C++ Template Parser" option makes CW8.3 incorrectly fail at + * expressions of the form sizeof(x) where x is an array local to a + * template function. + */ + +#pragma parse_func_templ off +#endif + +typedef multi_index_container<int> copyable_and_movable; + +struct holder +{ + copyable_and_movable c; +}; + +template<typename Sequence> +static void test_assign() +{ + Sequence s; + + int a[]={0,1,2,3,4,5}; + std::size_t sa=sizeof(a)/sizeof(a[0]); + + s.assign(&a[0],&a[sa]); + BOOST_TEST(s.size()==sa&&std::equal(s.begin(),s.end(),&a[0])); + + s.assign((const int*)(&a[0]),(const int*)(&a[sa])); + BOOST_TEST(s.size()==sa&&std::equal(s.begin(),s.end(),&a[0])); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + s.assign({0,1,2,3,4,5}); +#else + s.assign(&a[0],&a[sa]); +#endif + + BOOST_TEST(s.size()==sa&&std::equal(s.begin(),s.end(),&a[0])); + + s.assign((std::size_t)18,37); + BOOST_TEST(s.size()==18&&std::accumulate(s.begin(),s.end(),0)==666); + + s.assign((std::size_t)12,167); + BOOST_TEST(s.size()==12&&std::accumulate(s.begin(),s.end(),0)==2004); +} + +#if BOOST_WORKAROUND(__MWERKS__,<=0x3003) +#pragma parse_func_templ reset +#endif + +template<typename Sequence> +static void test_integral_assign() +{ + /* Special cases described in 23.1.1/9: integral types must not + * be taken as iterators in assign(f,l) and insert(p,f,l). + */ + + Sequence s; + + s.assign(5,10); + BOOST_TEST(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50); + s.assign(2u,5u); + BOOST_TEST(s.size()==2&&std::accumulate(s.begin(),s.end(),0)==10); + + s.clear(); + s.insert(s.begin(),5,10); + BOOST_TEST(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50); + s.insert(s.begin(),2u,5u); + BOOST_TEST(s.size()==7&&std::accumulate(s.begin(),s.end(),0)==60); +} + +employee_set produce_employee_set() +{ + employee_set es; + es.insert(employee(0,"Petr",60,2837)); + es.insert(employee(1,"Jiri",25,2143)); + es.insert(employee(2,"Radka",40,4875)); + es.insert(employee(3,"Milan",38,3474)); + return es; +} + +void test_copy_assignment() +{ + employee_set es; + employee_set es2(es); + + employee_set::allocator_type al=es.get_allocator(); + al=get<1>(es).get_allocator(); + al=get<2>(es).get_allocator(); + al=get<3>(es).get_allocator(); + al=get<4>(es).get_allocator(); + al=get<5>(es).get_allocator(); + + BOOST_TEST(es2.empty()); + + es2.insert(employee(0,"Joe",31,1123)); + es2.insert(employee(1,"Robert",27,5601)); + es2.insert(employee(2,"John",40,7889)); + es2.insert(employee(2,"Aristotle",2388,3357)); /* clash */ + es2.insert(employee(3,"Albert",20,9012)); + es2.insert(employee(4,"John",57,1002)); + es2.insert(employee(0,"Andrew",60,2302)); /* clash */ + + employee_set es3(es2); + + BOOST_TEST(es2==es3); + BOOST_TEST(get<2>(es2)==get<2>(es3)); + BOOST_TEST(get<3>(es2)==get<3>(es3)); + BOOST_TEST(get<5>(es2)==get<5>(es3)); + + employee_set es4=employee_set(non_std_allocator<employee>()); + employee_set_by_name& i1=get<name>(es4); + i1=get<1>(es2); + + BOOST_TEST(es4==es2); + + employee_set es5=employee_set(employee_set::ctor_args_list()); + employee_set_by_age& i2=get<age>(es5); + i2=get<2>(es2); + + BOOST_TEST(i2==get<2>(es2)); + + employee_set es6; + employee_set_as_inserted& i3=get<as_inserted>(es6); + i3=get<3>(es2); + + BOOST_TEST(i3==get<3>(es2)); + + employee_set es7; + employee_set_randomly& i5=get<randomly>(es7); + i5=get<5>(es2); + + BOOST_TEST(i5==get<5>(es2)); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)&&\ + !BOOST_WORKAROUND(BOOST_MSVC,==1800) /* MSVC 12.0 chokes on what follows */ + employee_set es8({{0,"Rose",40,4512},{1,"Mary",38,3345},{2,"Jo",25,7102}}); + employee_set es9; + es9={{0,"Rose",40,4512},{1,"Mary",38,3345},{2,"Jo",25,7102}, + {0,"Rose",40,4512}}; + + BOOST_TEST(es8.size()==3); + BOOST_TEST(es9==es8); + + es9.clear(); + get<0>(es9)={{0,"Rose",40,4512},{1,"Mary",38,3345},{2,"Jo",25,7102}, + {0,"Rose",40,4512}}; + BOOST_TEST(es9==es8); + + es9.clear(); + get<0>(es9)={{0,"Rose",40,4512},{2,"Jo",25,7102},{1,"Mary",38,3345}}; + BOOST_TEST(es9==es8); + + es9.clear(); + get<1>(es9)={{1,"Mary",38,3345},{0,"Rose",40,4512},{2,"Jo",25,7102}, + {0,"Rose",40,4512}}; + BOOST_TEST(es9==es8); + + es9.clear(); + get<2>(es9)={{2,"Jo",25,7102},{0,"Rose",40,4512},{1,"Mary",38,3345}}; + BOOST_TEST(es9==es8); + + es9.clear(); + get<3>(es9)={{0,"Rose",40,4512},{1,"Mary",38,3345},{1,"Mary",38,3345}, + {2,"Jo",25,7102}}; + BOOST_TEST(es9==es8); + + es9.clear(); + get<4>(es9)={{1,"Mary",38,3345},{2,"Jo",25,7102},{0,"Rose",40,4512}}; + BOOST_TEST(es9==es8); + + es9.clear(); + get<5>(es9)={{1,"Mary",38,3345},{2,"Jo",25,7102},{0,"Rose",40,4512}, + {2,"Jo",25,7102}}; + BOOST_TEST(es9==es8); +#endif + + employee_set es10(produce_employee_set()),es11(produce_employee_set()); + BOOST_TEST(es10==es11); + + employee_set es12(boost::move(es10)); + BOOST_TEST(es10.empty()); + BOOST_TEST(es11==es12); + + es10=boost::move(es12); + BOOST_TEST(es12.empty()); + BOOST_TEST(es11==es10); + + std::list<employee> l; + l.push_back(employee(3,"Anna",31,5388)); + l.push_back(employee(1,"Rachel",27,9012)); + l.push_back(employee(2,"Agatha",40,1520)); + + employee_set es13(l.begin(),l.end()); + + l.sort(); + + BOOST_TEST(es13.size()==l.size()&& + std::equal(es13.begin(),es13.end(),l.begin())); + + test_assign<multi_index_container<int,indexed_by<sequenced<> > > >(); + test_integral_assign< + multi_index_container<int,indexed_by<sequenced<> > > >(); + + test_assign<multi_index_container<int,indexed_by<random_access<> > > >(); + test_integral_assign< + multi_index_container<int,indexed_by<random_access<> > > >(); + + /* Testcase for problem described at http://www.boost.org/doc/html/move/ + * emulation_limitations.html#move.emulation_limitations.assignment_operator + */ + + holder h((holder())); + h=holder(); + +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) +{ + /* testcase for https://svn.boost.org/trac10/ticket/13518 */ + + multi_index_container<int> x={}; +} +#endif + + typedef small_allocator<int> small_alloc; + typedef multi_index_container< + int, + indexed_by< + ordered_unique<identity<int> >, + ranked_unique<identity<int> >, + hashed_unique<identity<int> >, + sequenced<>, + random_access<> + >, + small_alloc + > small_container; + typedef small_container::nth_index<0>::type small_container_0; + typedef small_container::nth_index<1>::type small_container_1; + typedef small_container::nth_index<2>::type small_container_2; + typedef small_container::nth_index<3>::type small_container_3; + typedef small_container::nth_index<4>::type small_container_4; + + BOOST_STATIC_ASSERT(( + boost::is_same<small_container::size_type,small_alloc::size_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same< + small_container::difference_type,small_alloc::difference_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same<small_container_0::size_type,small_alloc::size_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same< + small_container_0::difference_type,small_alloc::difference_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same<small_container_1::size_type,small_alloc::size_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same< + small_container_1::difference_type,small_alloc::difference_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same<small_container_2::size_type,small_alloc::size_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same< + small_container_2::difference_type,small_alloc::difference_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same<small_container_3::size_type,small_alloc::size_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same< + small_container_3::difference_type,small_alloc::difference_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same<small_container_4::size_type,small_alloc::size_type>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same< + small_container_4::difference_type,small_alloc::difference_type>::value)); + + small_container sc; + small_container_0& sc0=sc.get<0>(); + small_container_1& sc1=sc.get<1>(); + small_container_2& sc2=sc.get<2>(); + small_container_3& sc3=sc.get<3>(); + small_container_4& sc4=sc.get<4>(); + small_alloc::size_type s, + ms=(small_alloc::size_type)(-1); + + sc.insert(0); + + s=sc0.size(); + BOOST_TEST(sc0.max_size()<=ms); + s=sc0.erase(1); + s=sc0.count(0); + s=sc0.count(0,std::less<int>()); + + s=sc1.size(); + BOOST_TEST(sc1.max_size()<=ms); + s=sc1.erase(1); + s=sc1.count(0); + s=sc1.count(0,std::less<int>()); + (void)sc1.nth(s); + s=sc1.rank(sc1.begin()); + s=sc1.find_rank(0); + s=sc1.find_rank(0,std::less<int>()); + s=sc1.lower_bound_rank(0); + s=sc1.lower_bound_rank(0,std::less<int>()); + s=sc1.upper_bound_rank(0); + s=sc1.upper_bound_rank(0,std::less<int>()); + s=sc1.equal_range_rank(0).first; + s=sc1.equal_range_rank(0).second; + s=sc1.range_rank(unbounded,unbounded).first; + s=sc1.range_rank(unbounded,unbounded).second; + + s=sc2.size(); + BOOST_TEST(sc2.max_size()<=ms); + s=sc2.erase(1); + s=sc2.count(0); + s=sc2.count(0,boost::hash<int>(),std::equal_to<int>()); + s=sc2.bucket_count(); + BOOST_TEST(sc2.max_bucket_count()<=ms); + BOOST_TEST(sc2.bucket_size((small_alloc::size_type)(0))<=ms); + BOOST_TEST(sc2.bucket_size(0)<=ms); + (void)sc2.begin(0); + (void)sc2.end(0); + (void)sc2.cbegin(0); + (void)sc2.cend(0); + sc2.rehash(2); + sc2.reserve(2); + + s=sc3.size(); + BOOST_TEST(sc3.max_size()<=ms); + sc3.resize(0); + sc3.resize(0,0); + sc3.assign((small_alloc::size_type)(1),0); + sc3.insert(sc3.begin(),(small_alloc::size_type)(0),0); + + s=sc4.size(); + BOOST_TEST(sc4.max_size()<=ms); + BOOST_TEST(sc4.capacity()<=ms); + sc4.reserve(0); + sc4.resize(0); + sc4.resize(0,0); + sc4.assign((small_alloc::size_type)(1),0); + (void)sc4[0]; + (void)sc4.at(0); + sc4.insert(sc4.begin(),(small_alloc::size_type)(0),0); +} diff --git a/src/boost/libs/multi_index/test/test_copy_assignment.hpp b/src/boost/libs/multi_index/test/test_copy_assignment.hpp new file mode 100644 index 000000000..59a1ed5b5 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_copy_assignment.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for copying and assignment. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_copy_assignment(); diff --git a/src/boost/libs/multi_index/test/test_copy_assignment_main.cpp b/src/boost/libs/multi_index/test/test_copy_assignment_main.cpp new file mode 100644 index 000000000..e14bd973d --- /dev/null +++ b/src/boost/libs/multi_index/test/test_copy_assignment_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for copying and assignment. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_copy_assignment.hpp" + +int main() +{ + test_copy_assignment(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_hash_ops.cpp b/src/boost/libs/multi_index/test/test_hash_ops.cpp new file mode 100644 index 000000000..e85d905aa --- /dev/null +++ b/src/boost/libs/multi_index/test/test_hash_ops.cpp @@ -0,0 +1,118 @@ +/* Boost.MultiIndex test for standard hash operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include "test_hash_ops.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <iterator> +#include <boost/detail/lightweight_test.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/identity.hpp> +#include <vector> + +#include <iostream> + +using namespace boost::multi_index; + +template<typename HashedContainer> +void check_load_factor(const HashedContainer& hc) +{ + float lf=(float)hc.size()/hc.bucket_count(); + BOOST_TEST(lf<=hc.load_factor()+1.E-6); + BOOST_TEST(lf>=hc.load_factor()-1.E-6); + BOOST_TEST(lf<=hc.max_load_factor()+1.E-6); +} + +typedef multi_index_container< + int, + indexed_by< + hashed_unique<identity<int> > + > +> hash_container; + +void test_hash_ops() +{ + hash_container hc; + + BOOST_TEST(hc.max_load_factor()==1.0f); + BOOST_TEST(hc.bucket_count()<=hc.max_bucket_count()); + + hc.insert(1000); + hash_container::size_type buc=hc.bucket(1000); + hash_container::local_iterator it0=hc.begin(buc); + hash_container::local_iterator it1=hc.end(buc); + BOOST_TEST( + (hash_container::size_type)std::distance(it0,it1)==hc.bucket_size(buc)&& + hc.bucket_size(buc)==1&&*it0==1000); + + hc.clear(); + + for(hash_container::size_type s=2*hc.bucket_count();s--;){ + hc.insert((int)s); + } + check_load_factor(hc); + + hc.max_load_factor(0.5f); + BOOST_TEST(hc.max_load_factor()==0.5f); + hc.insert(-1); + check_load_factor(hc); + + hc.rehash(1); + BOOST_TEST(hc.bucket_count()>=1); + check_load_factor(hc); + + hc.max_load_factor(0.25f); + hc.rehash(1); + BOOST_TEST(hc.bucket_count()>=1); + check_load_factor(hc); + + hash_container::size_type bc=4*hc.bucket_count(); + hc.max_load_factor(0.125f); + hc.rehash(bc); + BOOST_TEST(hc.bucket_count()>=bc); + check_load_factor(hc); + + bc=2*hc.bucket_count(); + hc.rehash(bc); + BOOST_TEST(hc.bucket_count()>=bc); + check_load_factor(hc); + + hc.clear(); + hc.insert(0); + hc.rehash(1); + BOOST_TEST(hc.bucket_count()>=1); + check_load_factor(hc); + + hash_container hc2; + hc2.insert(0); + hc2.max_load_factor(0.5f/hc2.bucket_count()); + BOOST_TEST(hc2.load_factor()>hc2.max_load_factor()); + hc2.reserve(1); + BOOST_TEST(hc2.load_factor()<hc2.max_load_factor()); + + hash_container hc3; + hc3.clear(); + hc3.max_load_factor(1.0f); + hc3.reserve(1000); + hash_container::size_type bc3=hc3.bucket_count(); + BOOST_TEST(bc3>=1000); + std::vector<int> v; + for(unsigned int n=0;n<bc3;++n)v.push_back(n); + hc3.insert(v.begin(),v.end()); + BOOST_TEST(hc3.bucket_count()==bc3); /* LWG issue 2156 */ + hc3.max_load_factor(0.25f); + hc3.reserve(100); + BOOST_TEST(hc3.bucket_count()>bc3); + bc3=hc3.bucket_count(); + hc3.reserve((hash_container::size_type)(3.0f*hc3.max_load_factor()*bc3)); + BOOST_TEST(hc3.bucket_count()>bc3); +} diff --git a/src/boost/libs/multi_index/test/test_hash_ops.hpp b/src/boost/libs/multi_index/test/test_hash_ops.hpp new file mode 100644 index 000000000..37ebc4ada --- /dev/null +++ b/src/boost/libs/multi_index/test/test_hash_ops.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for standard hash operations. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_hash_ops(); diff --git a/src/boost/libs/multi_index/test/test_hash_ops_main.cpp b/src/boost/libs/multi_index/test/test_hash_ops_main.cpp new file mode 100644 index 000000000..be237b37e --- /dev/null +++ b/src/boost/libs/multi_index/test/test_hash_ops_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for standard hash operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_hash_ops.hpp" + +int main() +{ + test_hash_ops(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_iterators.cpp b/src/boost/libs/multi_index/test/test_iterators.cpp new file mode 100644 index 000000000..d9c7f7f20 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_iterators.cpp @@ -0,0 +1,250 @@ +/* Boost.MultiIndex test for iterators. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include "test_iterators.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include <boost/detail/lightweight_test.hpp> +#include <boost/next_prior.hpp> + +using namespace boost::multi_index; + +template<typename Index> +void test_non_const_iterators(Index& i,int target) +{ + typedef typename Index::iterator iterator; + typedef typename Index::reverse_iterator reverse_iterator; + + int n=0; + for(iterator it=i.begin();it!=i.end();++it){ + BOOST_TEST(i.iterator_to(*it)==it); + n+=it->id; + } + int m=0; + for(reverse_iterator rit=i.rbegin();rit!=i.rend();++rit){ + m+=rit->id; + } + int p=0; + for(iterator it2=i.end();it2!=i.begin();){ + --it2; + p+=it2->id; + } + int q=0; + for(reverse_iterator rit2=i.rend();rit2!=i.rbegin();){ + --rit2; + q+=rit2->id; + } + + BOOST_TEST(n==target&&n==m&&n==p&&n==q); +} + +template<typename Index> +void test_const_iterators(const Index& i,int target) +{ + typedef typename Index::const_iterator const_iterator; + typedef typename Index::const_reverse_iterator const_reverse_iterator; + + BOOST_TEST(i.cbegin()==i.begin()); + BOOST_TEST(i.cend()==i.end()); + BOOST_TEST(i.crbegin()==i.rbegin()); + BOOST_TEST(i.crend()==i.rend()); + + int n=0; + for(const_iterator it=i.begin();it!=i.end();++it){ + BOOST_TEST(i.iterator_to(*it)==it); + n+=it->id; + } + int m=0; + for(const_reverse_iterator rit=i.rbegin();rit!=i.rend();++rit){ + m+=rit->id; + } + int p=0; + for(const_iterator it2=i.end();it2!=i.begin();){ + --it2; + p+=it2->id; + } + int q=0; + for(const_reverse_iterator rit2=i.rend();rit2!=i.rbegin();){ + --rit2; + q+=rit2->id; + } + + BOOST_TEST(n==target&&n==m&&n==p&&n==q); +} + +template<typename Index> +void test_non_const_hashed_iterators(Index& i,int target) +{ + typedef typename Index::iterator iterator; + typedef typename Index::local_iterator local_iterator; + typedef typename Index::size_type size_type; + + int n=0; + for(iterator it=i.begin();it!=i.end();++it){ + BOOST_TEST(i.iterator_to(*it)==it); + n+=it->id; + } + int m=0; + for(size_type buc=0;buc<i.bucket_count();++buc){ + for(local_iterator it=i.begin(buc);it!=i.end(buc);++it){ + BOOST_TEST(i.local_iterator_to(*it)==it); + m+=it->id; + } + } + + BOOST_TEST(n==target&&n==m); +} + +template<typename Index> +void test_const_hashed_iterators(const Index& i,int target) +{ + typedef typename Index::const_iterator const_iterator; + typedef typename Index::const_local_iterator const_local_iterator; + typedef typename Index::size_type size_type; + + BOOST_TEST(i.cbegin()==i.begin()); + BOOST_TEST(i.cend()==i.end()); + + int n=0; + for(const_iterator it=i.begin();it!=i.end();++it){ + BOOST_TEST(i.iterator_to(*it)==it); + n+=it->id; + } + int m=0; + for(size_type buc=0;buc<i.bucket_count();++buc){ + BOOST_TEST(i.cbegin(buc)==i.begin(buc)); + BOOST_TEST(i.cend(buc)==i.end(buc)); + for(const_local_iterator it=i.begin(buc);it!=i.end(buc);++it){ + BOOST_TEST(i.local_iterator_to(*it)==it); + m+=it->id; + } + } + + BOOST_TEST(n==target&&n==m); +} + +template<typename Index> +void test_non_const_rnd_iterators(Index& i,int target) +{ + typedef typename Index::iterator iterator; + typedef typename Index::reverse_iterator reverse_iterator; + typedef typename Index::difference_type difference_type; + + iterator middle=i.begin()+(i.end()-i.begin())/2; + difference_type off=middle-i.begin(); + reverse_iterator rmiddle=i.rbegin()+off; + bool odd=((i.end()-i.begin())%2)!=0; + + int n=0; + for(iterator it=i.begin();it!=middle;++it){ + BOOST_TEST(i.iterator_to(*it)==it); + n+=it->id; + n+=it[off].id; + } + if(odd)n+=(boost::prior(i.end()))->id; + int m=0; + for(reverse_iterator rit=i.rbegin();rit!=rmiddle;++rit){ + m+=rit->id; + m+=(rit+off)->id; + } + if(odd)m+=(boost::prior(i.rend()))->id; + int p=0; + for(iterator it2=i.end();it2!=middle;){ + --it2; + p+=it2->id; + p+=(it2-off)->id; + } + if(odd)p-=middle->id; + int q=0; + for(reverse_iterator rit2=i.rend();rit2!=rmiddle;){ + --rit2; + q+=rit2->id; + q+=(rit2-off)->id; + } + if(odd)q-=rmiddle->id; + + BOOST_TEST(n==target&&n==m&&n==p&&n==q); +} + +template<typename Index> +void test_const_rnd_iterators(const Index& i,int target) +{ + typedef typename Index::const_iterator const_iterator; + typedef typename Index::const_reverse_iterator const_reverse_iterator; + typedef typename Index::difference_type difference_type; + + BOOST_TEST(i.cbegin()==i.begin()); + BOOST_TEST(i.cend()==i.end()); + BOOST_TEST(i.crbegin()==i.rbegin()); + BOOST_TEST(i.crend()==i.rend()); + + const_iterator middle=i.begin()+(i.end()-i.begin())/2; + difference_type off=middle-i.begin(); + const_reverse_iterator rmiddle=i.rbegin()+off; + bool odd=((i.end()-i.begin())%2)!=0; + + int n=0; + for(const_iterator it=i.begin();it!=middle;++it){ + BOOST_TEST(i.iterator_to(*it)==it); + n+=it->id; + n+=it[off].id; + } + if(odd)n+=(boost::prior(i.end()))->id; + int m=0; + for(const_reverse_iterator rit=i.rbegin();rit!=rmiddle;++rit){ + m+=rit->id; + m+=(rit+off)->id; + } + if(odd)m+=(boost::prior(i.rend()))->id; + int p=0; + for(const_iterator it2=i.end();it2!=middle;){ + --it2; + p+=it2->id; + p+=(it2-off)->id; + } + if(odd)p-=middle->id; + int q=0; + for(const_reverse_iterator rit2=i.rend();rit2!=rmiddle;){ + --rit2; + q+=rit2->id; + q+=(rit2-off)->id; + } + if(odd)q-=rmiddle->id; + + BOOST_TEST(n==target&&n==m&&n==p&&n==q); +} + +void test_iterators() +{ + employee_set es; + + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + es.insert(employee(3,"Albert",20,9012)); + es.insert(employee(4,"John",57,1002)); + + int target=0+1+2+3+4; + + test_non_const_iterators (es,target); + test_const_iterators (es,target); + test_non_const_hashed_iterators(get<1>(es),target); + test_const_hashed_iterators (get<1>(es),target); + test_non_const_iterators (get<2>(es),target); + test_const_iterators (get<2>(es),target); + test_non_const_iterators (get<3>(es),target); + test_const_iterators (get<3>(es),target); + test_non_const_hashed_iterators(get<4>(es),target); + test_const_hashed_iterators (get<4>(es),target); + test_non_const_rnd_iterators (get<5>(es),target); + test_const_rnd_iterators (get<5>(es),target); +} diff --git a/src/boost/libs/multi_index/test/test_iterators.hpp b/src/boost/libs/multi_index/test/test_iterators.hpp new file mode 100644 index 000000000..01ffab21e --- /dev/null +++ b/src/boost/libs/multi_index/test/test_iterators.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for iterators. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_iterators(); diff --git a/src/boost/libs/multi_index/test/test_iterators_main.cpp b/src/boost/libs/multi_index/test/test_iterators_main.cpp new file mode 100644 index 000000000..13bd39ae2 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_iterators_main.cpp @@ -0,0 +1,19 @@ +/* Boost.MultiIndex test for iterators. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_iterators.hpp" + +int main() +{ + test_iterators(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/multi_index/test/test_key.cpp b/src/boost/libs/multi_index/test/test_key.cpp new file mode 100644 index 000000000..10ebb37e7 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_key.cpp @@ -0,0 +1,170 @@ +/* Boost.MultiIndex test for terse key specification syntax. + * + * Copyright 2003-2019 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/multi_index for library home page. + */ + +#include "test_key.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/detail/lightweight_test.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index/key.hpp> + +#if !defined(BOOST_MULTI_INDEX_KEY_SUPPORTED) + +#include <boost/config/pragma_message.hpp> + +BOOST_PRAGMA_MESSAGE("boost::multi_index::key not supported, skipping test") + +void test_key() +{ +} +#else + +#include <functional> +#include <type_traits> + +using namespace boost::multi_index; + +namespace { + +struct base +{ + int x; + const int cx; + int f(){return x;}; + int cf()const{return x;}; + int vf()volatile{return x;}; + int cvf()const volatile{return x;}; + int rf()&{return x;}; + int crf()const&{return x;}; + int vrf()volatile&{return x;}; + int cvrf()const volatile&{return x;}; + int nef()noexcept{return x;}; + int cnef()const noexcept{return x;}; + int vnef()volatile noexcept{return x;}; + int cvnef()const volatile noexcept{return x;}; + int rnef()& noexcept{return x;}; + int crnef()const& noexcept{return x;}; + int vrnef()volatile& noexcept{return x;}; + int cvrnef()const volatile& noexcept{return x;}; +}; + +int gf(const base& b){return b.x;} +int negf(const base& b)noexcept{return b.x;} + +struct derived:base +{ + int y; +}; + +int gh(derived& d){return d.y;} +int grh(std::reference_wrapper<derived>& d){return d.get().y;} + +} /* namespace */ + +void test_key() +{ + BOOST_TEST((std::is_same< + key<&base::x>,member<base,int,&base::x> + >::value)); + BOOST_TEST((std::is_same< + key<&base::cx>,member<base,const int,&base::cx> + >::value)); + BOOST_TEST((std::is_same< + key<&base::f>,mem_fun<base,int,&base::f> + >::value)); + BOOST_TEST((std::is_same< + key<&base::cf>,const_mem_fun<base,int,&base::cf> + >::value)); + BOOST_TEST((std::is_same< + key<&base::vf>,volatile_mem_fun<base,int,&base::vf> + >::value)); + BOOST_TEST((std::is_same< + key<&base::cvf>,cv_mem_fun<base,int,&base::cvf> + >::value)); + BOOST_TEST((std::is_same< + key<&base::rf>,ref_mem_fun<base,int,&base::rf> + >::value)); + BOOST_TEST((std::is_same< + key<&base::crf>,cref_mem_fun<base,int,&base::crf> + >::value)); + BOOST_TEST((std::is_same< + key<&base::vrf>,vref_mem_fun<base,int,&base::vrf> + >::value)); + BOOST_TEST((std::is_same< + key<&base::cvrf>,cvref_mem_fun<base,int,&base::cvrf> + >::value)); + BOOST_TEST((std::is_same< + key<&base::nef>,mem_fun<base,int,&base::nef> + >::value)); + BOOST_TEST((std::is_same< + key<&base::cnef>,const_mem_fun<base,int,&base::cnef> + >::value)); + BOOST_TEST((std::is_same< + key<&base::vnef>,volatile_mem_fun<base,int,&base::vnef> + >::value)); + BOOST_TEST((std::is_same< + key<&base::cvnef>,cv_mem_fun<base,int,&base::cvnef> + >::value)); + BOOST_TEST((std::is_same< + key<&base::rnef>,ref_mem_fun<base,int,&base::rnef> + >::value)); + BOOST_TEST((std::is_same< + key<&base::crnef>,cref_mem_fun<base,int,&base::crnef> + >::value)); + BOOST_TEST((std::is_same< + key<&base::vrnef>,vref_mem_fun<base,int,&base::vrnef> + >::value)); + BOOST_TEST((std::is_same< + key<&base::cvrnef>,cvref_mem_fun<base,int,&base::cvrnef> + >::value)); + BOOST_TEST((std::is_same< + key<gf>,global_fun<const base&,int,gf> + >::value)); + BOOST_TEST((std::is_same< + key<negf>,global_fun<const base&,int,negf> + >::value)); + BOOST_TEST((std::is_same< + key<&base::x,&base::cx,&base::f,&base::cf,gf>, + composite_key< + base, + member<base,int,&base::x>, + member<base,const int,&base::cx>, + mem_fun<base,int,&base::f>, + const_mem_fun<base,int,&base::cf>, + global_fun<const base&,int,gf> + > + >::value)); + BOOST_TEST((std::is_same< + key<&base::x,&derived::y>, + composite_key< + derived, + member<base,int,&base::x>, + member<derived,int,&derived::y> + > + >::value)); + BOOST_TEST((std::is_same< + key<gf,gh>, + composite_key< + derived, + global_fun<const base&,int,gf>, + global_fun<derived&,int,gh> + > + >::value)); + BOOST_TEST((std::is_same< + key<gf,gh,grh>, + composite_key< + std::reference_wrapper<derived>, + global_fun<const base&,int,gf>, + global_fun<derived&,int,gh>, + global_fun<std::reference_wrapper<derived>&,int,grh> + > + >::value)); +} +#endif diff --git a/src/boost/libs/multi_index/test/test_key.hpp b/src/boost/libs/multi_index/test/test_key.hpp new file mode 100644 index 000000000..9ebe4fe66 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_key.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for terse key specification syntax. + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +void test_key(); diff --git a/src/boost/libs/multi_index/test/test_key_extractors.cpp b/src/boost/libs/multi_index/test/test_key_extractors.cpp new file mode 100644 index 000000000..31eec101f --- /dev/null +++ b/src/boost/libs/multi_index/test/test_key_extractors.cpp @@ -0,0 +1,604 @@ +/* Boost.MultiIndex test for key extractors. + * + * Copyright 2003-2020 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/multi_index for library home page. + */ + +#include "test_key_extractors.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/detail/lightweight_test.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index/key_extractors.hpp> +#include <boost/ref.hpp> +#include <boost/scoped_ptr.hpp> +#include <list> + +using namespace boost::multi_index; +using namespace boost::tuples; + +struct test_class +{ + int int_member; + const int int_cmember; + + bool bool_mem_fun_const()const{return true;} + bool bool_mem_fun(){return false;} + bool bool_mem_fun_volatile()volatile{return false;} + bool bool_mem_fun_cv()const volatile{return true;} + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + + bool bool_mem_fun_cref()const&{return true;} + bool bool_mem_fun_ref()&{return false;} + bool bool_mem_fun_vref()volatile&{return false;} + bool bool_mem_fun_cvref()const volatile&{return true;} + +#endif + + static bool bool_global_fun(test_class){return true;} + static bool bool_global_fun_const_ref(const test_class&){return false;} + static bool bool_global_fun_ref(test_class&){return true;} + + test_class(int i=0):int_member(i),int_cmember(i){} + test_class(int i,int j):int_member(i),int_cmember(j){} + test_class(const test_class& x): + int_member(x.int_member),int_cmember(x.int_cmember){} + + test_class& operator=(const test_class& x) + { + int_member=x.int_member; + return *this; + } + + bool operator<(const test_class& x)const + { + if(int_member<x.int_member)return true; + if(x.int_member<int_member)return false; + return int_cmember<x.int_cmember; + } + + bool operator==(const test_class& x)const + { + return int_member==x.int_member&&int_cmember==x.int_cmember; + } +}; + +struct test_derived_class:test_class +{ + test_derived_class(int i=0):test_class(i){} + test_derived_class(int i,int j):test_class(i,j){} +}; + +typedef identity<test_class> idn; +typedef identity<const test_class> cidn; +typedef BOOST_MULTI_INDEX_MEMBER(test_class,int,int_member) key_m; +typedef BOOST_MULTI_INDEX_MEMBER(test_class,const int,int_member) ckey_m; +typedef BOOST_MULTI_INDEX_MEMBER(test_class,const int,int_cmember) key_cm; +typedef BOOST_MULTI_INDEX_MEM_FUN(test_class,bool,bool_mem_fun) key_mf; +typedef BOOST_MULTI_INDEX_CONST_MEM_FUN( + test_class,bool,bool_mem_fun_const) key_cmf; +typedef volatile_mem_fun< + test_class,bool,&test_class::bool_mem_fun_volatile> key_vmf; +typedef cv_mem_fun<test_class,bool,&test_class::bool_mem_fun_cv> key_cvmf; + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + +typedef cref_mem_fun< + test_class,bool,&test_class::bool_mem_fun_cref> key_crmf; +typedef ref_mem_fun<test_class,bool,&test_class::bool_mem_fun_ref> key_rmf; +typedef vref_mem_fun< + test_class,bool,&test_class::bool_mem_fun_vref> key_vrmf; +typedef cvref_mem_fun< + test_class,bool,&test_class::bool_mem_fun_cvref> key_cvrmf; + +#endif + +typedef global_fun<test_class,bool,&test_class::bool_global_fun> key_gf; +typedef global_fun< + const test_class&,bool, + &test_class::bool_global_fun_const_ref + > key_gcrf; +typedef global_fun< + test_class&,bool, + &test_class::bool_global_fun_ref + > key_grf; +typedef composite_key< + test_class, + idn, + key_m, + key_cm, + key_cmf + > compkey; +typedef composite_key< + test_class, + cidn, + ckey_m + > ccompkey; +typedef composite_key< + boost::reference_wrapper<test_class>, + key_mf + > ccompw_key; + +#if !defined(BOOST_NO_SFINAE) +/* testcases for problems with non-copyable classes reported at + * http://lists.boost.org/Archives/boost/2006/04/103065.php + */ + +struct test_nc_class +{ + int int_member; + const int int_cmember; + + bool bool_mem_fun_const()const{return true;} + bool bool_mem_fun(){return false;} + + static bool bool_global_fun_const_ref(const test_nc_class&){return false;} + static bool bool_global_fun_ref(test_nc_class&){return true;} + + test_nc_class(int i=0):int_member(i),int_cmember(i){} + test_nc_class(int i,int j):int_member(i),int_cmember(j){} + + bool operator==(const test_nc_class& x)const + { + return int_member==x.int_member&&int_cmember==x.int_cmember; + } + +private: + test_nc_class(const test_nc_class&); + test_nc_class& operator=(const test_nc_class&); +}; + +struct test_nc_derived_class:test_nc_class +{ + test_nc_derived_class(int i=0):test_nc_class(i){} + test_nc_derived_class(int i,int j):test_nc_class(i,j){} +}; + +typedef identity<test_nc_class> nc_idn; +typedef identity<const test_nc_class> nc_cidn; +typedef BOOST_MULTI_INDEX_MEMBER(test_nc_class,int,int_member) nc_key_m; +typedef BOOST_MULTI_INDEX_MEMBER( + test_nc_class,const int,int_member) nc_ckey_m; +typedef BOOST_MULTI_INDEX_CONST_MEM_FUN( + test_nc_class,bool,bool_mem_fun_const) nc_key_cmf; +typedef BOOST_MULTI_INDEX_MEM_FUN( + test_nc_class,bool,bool_mem_fun) nc_key_mf; +typedef global_fun< + const test_nc_class&,bool, + &test_nc_class::bool_global_fun_const_ref + > nc_key_gcrf; +typedef global_fun< + test_nc_class&,bool, + &test_nc_class::bool_global_fun_ref + > nc_key_grf; +typedef composite_key< + test_nc_class, + nc_idn, + nc_key_m, + nc_ckey_m, + nc_key_cmf + > nc_compkey; +#endif + +void test_key_extractors() +{ + idn id; + cidn cid; + key_m k_m; + ckey_m ck_m; + key_cm k_cm; + key_cmf k_cmf; + key_mf k_mf; + key_vmf k_vmf; + key_cvmf k_cvmf; +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + key_crmf k_crmf; + key_rmf k_rmf; + key_vrmf k_vrmf; + key_cvrmf k_cvrmf; +#endif + key_gf k_gf; + key_gcrf k_gcrf; + key_grf k_grf; + compkey cmpk; + ccompkey ccmpk; + ccompw_key ccmpk_w; + + test_derived_class td(-1,0); + const test_derived_class& ctdr=td; + + test_class& tr=td; + const test_class& ctr=tr; + + test_derived_class* tdp=&td; + const test_derived_class* ctdp=&ctdr; + + test_class* tp=&tr; + const test_class* ctp=&tr; + + test_class** tpp=&tp; + const test_class** ctpp=&ctp; + + boost::scoped_ptr<test_class*> tap(new test_class*(tp)); + boost::scoped_ptr<const test_class*> ctap(new const test_class*(ctp)); + + boost::reference_wrapper<test_class> tw(tr); + boost::reference_wrapper<const test_class> ctw(tr); + + id(tr).int_member=0; + BOOST_TEST(id(tr).int_member==0); + BOOST_TEST(cid(tr).int_member==0); + BOOST_TEST(k_m(tr)==0); + BOOST_TEST(ck_m(tr)==0); + BOOST_TEST(cmpk(tr)==make_tuple(test_class(0,0),0,0,true)); + BOOST_TEST(ccmpk(tr)==make_tuple(test_class(0,0),0)); + BOOST_TEST(id(ctr).int_member==0); + BOOST_TEST(cid(ctr).int_member==0); + BOOST_TEST(k_m(ctr)==0); + BOOST_TEST(ck_m(ctr)==0); + BOOST_TEST(cmpk(ctr)==make_tuple(test_class(0,0),0,0,true)); + BOOST_TEST(ccmpk(ctr)==make_tuple(test_class(0,0),0)); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(id(td).int_member==0); + BOOST_TEST(cid(td).int_member==0); + BOOST_TEST(k_m(td)==0); + BOOST_TEST(ck_m(td)==0); + BOOST_TEST(cmpk(td)==make_tuple(test_class(0,0),0,0,true)); + BOOST_TEST(ccmpk(td)==make_tuple(test_class(0,0),0)); + BOOST_TEST(id(ctdr).int_member==0); + BOOST_TEST(cid(ctdr).int_member==0); + BOOST_TEST(k_m(ctdr)==0); + BOOST_TEST(ck_m(ctdr)==0); + BOOST_TEST(cmpk(ctdr)==make_tuple(test_class(0,0),0,0,true)); + BOOST_TEST(ccmpk(ctdr)==make_tuple(test_class(0,0),0)); +#endif + + k_m(tr)=1; + BOOST_TEST(id(tp).int_member==1); + BOOST_TEST(cid(tp).int_member==1); + BOOST_TEST(k_m(tp)==1); + BOOST_TEST(ck_m(tp)==1); + BOOST_TEST(cmpk(tp)==make_tuple(test_class(1,0),1,0,true)); + BOOST_TEST(ccmpk(tp)==make_tuple(test_class(1,0),1)); + BOOST_TEST(cid(ctp).int_member==1); + BOOST_TEST(ck_m(ctp)==1); + BOOST_TEST(cmpk(ctp)==make_tuple(test_class(1,0),1,0,true)); + BOOST_TEST(ccmpk(ctp)==make_tuple(test_class(1,0),1)); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(id(tdp).int_member==1); + BOOST_TEST(cid(tdp).int_member==1); + BOOST_TEST(k_m(tdp)==1); + BOOST_TEST(ck_m(tdp)==1); + BOOST_TEST(cmpk(tdp)==make_tuple(test_class(1,0),1,0,true)); + BOOST_TEST(ccmpk(tdp)==make_tuple(test_class(1,0),1)); + BOOST_TEST(cid(ctdp).int_member==1); + BOOST_TEST(ck_m(ctdp)==1); + BOOST_TEST(cmpk(ctdp)==make_tuple(test_class(1,0),1,0,true)); + BOOST_TEST(ccmpk(ctdp)==make_tuple(test_class(1,0),1)); +#endif + + k_m(tp)=2; + BOOST_TEST(id(tpp).int_member==2); + BOOST_TEST(cid(tpp).int_member==2); + BOOST_TEST(k_m(tpp)==2); + BOOST_TEST(ck_m(tpp)==2); + BOOST_TEST(cmpk(tpp)==make_tuple(test_class(2,0),2,0,true)); + BOOST_TEST(ccmpk(tpp)==make_tuple(test_class(2,0),2)); + BOOST_TEST(cid(ctpp).int_member==2); + BOOST_TEST(ck_m(ctpp)==2); + BOOST_TEST(cmpk(ctpp)==make_tuple(test_class(2,0),2,0,true)); + BOOST_TEST(ccmpk(ctpp)==make_tuple(test_class(2,0),2)); + + k_m(tpp)=3; + BOOST_TEST(id(tap).int_member==3); + BOOST_TEST(cid(tap).int_member==3); + BOOST_TEST(k_m(tap)==3); + BOOST_TEST(ck_m(tap)==3); + BOOST_TEST(cmpk(tap)==make_tuple(test_class(3,0),3,0,true)); + BOOST_TEST(ccmpk(tap)==make_tuple(test_class(3,0),3)); + BOOST_TEST(cid(ctap).int_member==3); + BOOST_TEST(ck_m(ctap)==3); + BOOST_TEST(cmpk(ctap)==make_tuple(test_class(3,0),3,0,true)); + BOOST_TEST(ccmpk(ctap)==make_tuple(test_class(3,0),3)); + + k_m(tap)=4; + BOOST_TEST(id(tw).int_member==4); + BOOST_TEST(cid(tw).int_member==4); + BOOST_TEST(k_m(tw)==4); + BOOST_TEST(ck_m(tw)==4); + BOOST_TEST(cmpk(tw)==make_tuple(test_class(4,0),4,0,true)); + BOOST_TEST(ccmpk(tw)==make_tuple(test_class(4,0),4)); + + k_m(tw)=5; + BOOST_TEST(id(ctw).int_member==5); + BOOST_TEST(cid(ctw).int_member==5); + BOOST_TEST(k_m(ctw)==5); + BOOST_TEST(ck_m(ctw)==5); + BOOST_TEST(cmpk(ctw)==make_tuple(test_class(5,0),5,0,true)); + BOOST_TEST(ccmpk(ctw)==make_tuple(test_class(5,0),5)); + + BOOST_TEST(k_cm(tr)==0); + BOOST_TEST(k_cm(ctr)==0); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(k_cm(td)==0); + BOOST_TEST(k_cm(ctdr)==0); +#endif + + BOOST_TEST(k_cm(tp)==0); + BOOST_TEST(k_cm(ctp)==0); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(k_cm(tdp)==0); + BOOST_TEST(k_cm(ctdp)==0); +#endif + + BOOST_TEST(k_cm(tpp)==0); + BOOST_TEST(k_cm(ctpp)==0); + BOOST_TEST(k_cm(tap)==0); + BOOST_TEST(k_cm(ctap)==0); + + BOOST_TEST(k_cm(tw)==0); + BOOST_TEST(k_cm(ctw)==0); + + BOOST_TEST(k_cmf(tr)); + BOOST_TEST(k_cmf(ctr)); + BOOST_TEST(k_cvmf(tr)); + BOOST_TEST(k_cvmf(ctr)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(k_crmf(tr)); + BOOST_TEST(k_crmf(ctr)); + BOOST_TEST(k_cvrmf(tr)); + BOOST_TEST(k_cvrmf(ctr)); +#endif + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(k_cmf(td)); + BOOST_TEST(k_cmf(ctdr)); + BOOST_TEST(k_cvmf(td)); + BOOST_TEST(k_cvmf(ctdr)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(k_crmf(td)); + BOOST_TEST(k_crmf(ctdr)); + BOOST_TEST(k_cvrmf(td)); + BOOST_TEST(k_cvrmf(ctdr)); +#endif +#endif + + BOOST_TEST(k_cmf(tp)); + BOOST_TEST(k_cmf(ctp)); + BOOST_TEST(k_cvmf(tp)); + BOOST_TEST(k_cvmf(ctp)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(k_crmf(tp)); + BOOST_TEST(k_crmf(ctp)); + BOOST_TEST(k_cvrmf(tp)); + BOOST_TEST(k_cvrmf(ctp)); +#endif + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(k_cmf(tdp)); + BOOST_TEST(k_cmf(ctdp)); + BOOST_TEST(k_cvmf(tdp)); + BOOST_TEST(k_cvmf(ctdp)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(k_crmf(tdp)); + BOOST_TEST(k_crmf(ctdp)); + BOOST_TEST(k_cvrmf(tdp)); + BOOST_TEST(k_cvrmf(ctdp)); +#endif +#endif + + BOOST_TEST(k_cmf(tpp)); + BOOST_TEST(k_cmf(ctpp)); + BOOST_TEST(k_cmf(tap)); + BOOST_TEST(k_cmf(ctap)); + BOOST_TEST(k_cvmf(tpp)); + BOOST_TEST(k_cvmf(ctpp)); + BOOST_TEST(k_cvmf(tap)); + BOOST_TEST(k_cvmf(ctap)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(k_crmf(tpp)); + BOOST_TEST(k_crmf(ctpp)); + BOOST_TEST(k_crmf(tap)); + BOOST_TEST(k_crmf(ctap)); + BOOST_TEST(k_cvrmf(tpp)); + BOOST_TEST(k_cvrmf(ctpp)); + BOOST_TEST(k_cvrmf(tap)); + BOOST_TEST(k_cvrmf(ctap)); +#endif + + BOOST_TEST(k_cmf(tw)); + BOOST_TEST(k_cmf(ctw)); + BOOST_TEST(k_cvmf(tw)); + BOOST_TEST(k_cvmf(ctw)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(k_crmf(tw)); + BOOST_TEST(k_crmf(ctw)); + BOOST_TEST(k_cvrmf(tw)); + BOOST_TEST(k_cvrmf(ctw)); +#endif + + BOOST_TEST(!k_mf(tr)); + BOOST_TEST(!k_vmf(tr)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(!k_rmf(tr)); + BOOST_TEST(!k_vrmf(tr)); +#endif + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(!k_mf(td)); + BOOST_TEST(!k_vmf(td)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(!k_rmf(td)); + BOOST_TEST(!k_vrmf(td)); +#endif +#endif + + BOOST_TEST(!k_mf(tp)); + BOOST_TEST(!k_vmf(tp)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(!k_rmf(tp)); + BOOST_TEST(!k_vrmf(tp)); +#endif + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(!k_mf(tdp)); + BOOST_TEST(!k_vmf(tdp)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(!k_rmf(tdp)); + BOOST_TEST(!k_vrmf(tdp)); +#endif +#endif + + BOOST_TEST(!k_mf(tpp)); + BOOST_TEST(!k_mf(tap)); + BOOST_TEST(!k_mf(tw)); + BOOST_TEST(!k_vmf(tpp)); + BOOST_TEST(!k_vmf(tap)); + BOOST_TEST(!k_vmf(tw)); + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + BOOST_TEST(!k_rmf(tpp)); + BOOST_TEST(!k_rmf(tap)); + BOOST_TEST(!k_rmf(tw)); + BOOST_TEST(!k_vrmf(tpp)); + BOOST_TEST(!k_vrmf(tap)); + BOOST_TEST(!k_vrmf(tw)); +#endif + + BOOST_TEST(k_gf(tr)); + BOOST_TEST(k_gf(ctr)); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(k_gf(td)); + BOOST_TEST(k_gf(ctdr)); +#endif + + BOOST_TEST(k_gf(tp)); + BOOST_TEST(k_gf(ctp)); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(k_gf(tdp)); + BOOST_TEST(k_gf(ctdp)); +#endif + + BOOST_TEST(k_gf(tpp)); + BOOST_TEST(k_gf(ctpp)); + BOOST_TEST(k_gf(tap)); + BOOST_TEST(k_gf(ctap)); + + BOOST_TEST(k_gf(tw)); + BOOST_TEST(k_gf(ctw)); + + BOOST_TEST(!k_gcrf(tr)); + BOOST_TEST(!k_gcrf(ctr)); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(!k_gcrf(td)); + BOOST_TEST(!k_gcrf(ctdr)); +#endif + + BOOST_TEST(!k_gcrf(tp)); + BOOST_TEST(!k_gcrf(ctp)); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(!k_gcrf(tdp)); + BOOST_TEST(!k_gcrf(ctdp)); +#endif + + BOOST_TEST(!k_gcrf(tpp)); + BOOST_TEST(!k_gcrf(ctpp)); + BOOST_TEST(!k_gcrf(tap)); + BOOST_TEST(!k_gcrf(ctap)); + + BOOST_TEST(!k_gcrf(tw)); + BOOST_TEST(!k_gcrf(ctw)); + + BOOST_TEST(k_grf(tr)); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(k_grf(td)); +#endif + + BOOST_TEST(k_grf(tp)); + +#if !defined(BOOST_NO_SFINAE) + BOOST_TEST(k_grf(tdp)); +#endif + + BOOST_TEST(k_grf(tpp)); + BOOST_TEST(k_grf(tap)); + BOOST_TEST(k_grf(tw)); + + BOOST_TEST(ccmpk_w(tw)==make_tuple(false)); + +#if !defined(BOOST_NO_SFINAE) +/* testcases for problems with non-copyable classes reported at + * http://lists.boost.org/Archives/boost/2006/04/103065.php + */ + + nc_idn nc_id; + nc_cidn nc_cid; + nc_key_m nc_k_m; + nc_ckey_m nc_ck_m; + nc_key_cmf nc_k_cmf; + nc_key_mf nc_k_mf; + nc_key_gcrf nc_k_gcrf; + nc_key_grf nc_k_grf; + nc_compkey nc_cmpk; + + test_nc_derived_class nc_td(-1,0); + + nc_id(nc_td).int_member=0; + BOOST_TEST(nc_id(nc_td).int_member==0); + BOOST_TEST(nc_cid(nc_td).int_member==0); + + nc_k_m(&nc_td)=1; + BOOST_TEST(nc_k_m(&nc_td)==1); + BOOST_TEST(nc_ck_m(&nc_td)==1); + + BOOST_TEST(nc_k_cmf(nc_td)); + BOOST_TEST(!nc_k_mf(nc_td)); + + BOOST_TEST(!nc_k_gcrf(nc_td)); + BOOST_TEST(nc_k_grf(nc_td)); + + test_nc_class nc_t(1,0); + BOOST_TEST(nc_cmpk(nc_td)==make_tuple(boost::cref(nc_t),1,1,true)); +#endif + + std::list<test_class> tl; + for(int i=0;i<20;++i)tl.push_back(test_class(i)); + + int j=0; + for(std::list<test_class>::iterator it=tl.begin();it!=tl.end();++it){ + BOOST_TEST(k_m(it)==j); + BOOST_TEST(k_cm(it)==j); + BOOST_TEST(k_cmf(it)); + BOOST_TEST(!k_mf(it)); + BOOST_TEST(k_gf(it)); + BOOST_TEST(!k_gcrf(it)); + BOOST_TEST(k_grf(it)); + BOOST_TEST(cmpk(it)==make_tuple(test_class(j),j,j,true)); + BOOST_TEST(ccmpk(it)==make_tuple(test_class(j),j)); + ++j; + } +} diff --git a/src/boost/libs/multi_index/test/test_key_extractors.hpp b/src/boost/libs/multi_index/test/test_key_extractors.hpp new file mode 100644 index 000000000..cee8ac099 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_key_extractors.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for key extractors. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_key_extractors(); diff --git a/src/boost/libs/multi_index/test/test_key_extractors_main.cpp b/src/boost/libs/multi_index/test/test_key_extractors_main.cpp new file mode 100644 index 000000000..3887daff9 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_key_extractors_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for key extractors. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_key_extractors.hpp" + +int main() +{ + test_key_extractors(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_key_main.cpp b/src/boost/libs/multi_index/test/test_key_main.cpp new file mode 100644 index 000000000..a4d012a85 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_key_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for terse key specification syntax. + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_key.hpp" + +int main() +{ + test_key(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_list_ops.cpp b/src/boost/libs/multi_index/test/test_list_ops.cpp new file mode 100644 index 000000000..e67fda7f8 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_list_ops.cpp @@ -0,0 +1,275 @@ +/* Boost.MultiIndex test for standard list operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include "test_list_ops.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <vector> +#include <boost/detail/lightweight_test.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/multi_index/random_access_index.hpp> +#include <boost/preprocessor/seq/enum.hpp> + +using namespace boost::multi_index; + +#undef CHECK_EQUAL +#define CHECK_EQUAL(p,check_seq) \ +{\ + int v[]={BOOST_PP_SEQ_ENUM(check_seq)};\ + std::size_t size_v=sizeof(v)/sizeof(int);\ + BOOST_TEST(std::size_t(std::distance((p).begin(),(p).end()))==size_v);\ + BOOST_TEST(std::equal((p).begin(),(p).end(),&v[0]));\ +} + +#undef CHECK_VOID_RANGE +#define CHECK_VOID_RANGE(p) BOOST_TEST((p).first==(p).second) + +struct is_even +{ + bool operator()(int x)const{return x%2==0;} +}; + +template <int m> +struct same_integral_div +{ + bool operator()(int x,int y)const{return (x/m)==(y/m);} +}; + +template <typename Container,typename Compare> +bool is_sorted( + const Container& c,const Compare& comp=Compare()) +{ + if(c.empty())return true; + + typedef typename Container::const_iterator const_iterator; + for(const_iterator it(c.begin());;){ + const_iterator it2=it; + ++it2; + if(it2==c.end())return true; + if(comp(*it2,*it))return false; + it=it2; + } +} + +#if BOOST_WORKAROUND(__MWERKS__,<=0x3003) +/* The "ISO C++ Template Parser" option makes CW8.3 incorrectly fail at + * expressions of the form sizeof(x) where x is an array local to a + * template function. + */ + +#pragma parse_func_templ off +#endif + +template<typename Sequence> +static void test_list_ops_unique_seq() +{ + typedef typename nth_index<Sequence,1>::type sequenced_index; + + Sequence ss,ss2; + sequenced_index &si=get<1>(ss),&si2=get<1>(ss2); + + si.push_front(0); /* 0 */ + si.push_front(4); /* 40 */ + ss.insert(2); /* 402 */ + ss.insert(5); /* 4025 */ + si.push_front(3); /* 34025 */ + si.push_back(6); /* 340256 */ + si.push_back(1); /* 3402561 */ + si.insert(project<1>(ss,ss.find(2)),8); /* 34082561 */ + si2=si; + + CHECK_EQUAL(si,(3)(4)(0)(8)(2)(5)(6)(1)); + + si.remove(8); + CHECK_EQUAL(si,(3)(4)(0)(2)(5)(6)(1)); + + si.remove_if(is_even()); + + CHECK_EQUAL(si,(3)(5)(1)); + + si.splice(si.end(),si2); + CHECK_EQUAL(si,(3)(5)(1)(4)(0)(8)(2)(6)); + CHECK_EQUAL(si2,(3)(5)(1)); + + si.splice(project<1>(ss,ss.find(4)),si,project<1>(ss,ss.find(8))); + CHECK_EQUAL(si,(3)(5)(1)(8)(4)(0)(2)(6)); + si2.clear(); + si2.splice(si2.begin(),si,si.begin()); + + si.splice(si.end(),si2,si2.begin()); + CHECK_EQUAL(si,(5)(1)(8)(4)(0)(2)(6)(3)); + BOOST_TEST(si2.empty()); + + si2.splice(si2.end(),si,project<1>(ss,ss.find(0)),project<1>(ss,ss.find(6))); + CHECK_EQUAL(si,(5)(1)(8)(4)(6)(3)); + CHECK_EQUAL(si2,(0)(2)); + + si.splice(si.begin(),si,si.begin(),si.begin()); + CHECK_EQUAL(si,(5)(1)(8)(4)(6)(3)); + + si.splice(project<1>(ss,ss.find(8)),si,project<1>(ss,ss.find(4)),si.end()); + CHECK_EQUAL(si,(5)(1)(4)(6)(3)(8)); + + si.sort(); + si2.sort(); + BOOST_TEST(is_sorted(si,std::less<int>())); + BOOST_TEST(is_sorted(si2,std::less<int>())); + + si.merge(si2); + BOOST_TEST(is_sorted(si,std::less<int>())); + BOOST_TEST(si2.empty()); + + { + Sequence ss3(ss); + sequenced_index &si3=get<1>(ss3); + + si3.sort(std::greater<int>()); + si.reverse(); + BOOST_TEST(si==si3); + } + + si2.splice(si2.end(),si,project<1>(ss,ss.find(6)),project<1>(ss,ss.find(3))); + CHECK_EQUAL(si2,(6)(5)(4)); + + si.merge(si2,std::greater<int>()); + BOOST_TEST(is_sorted(si,std::greater<int>())); + BOOST_TEST(si2.empty()); + + /* testcase for bug reported at + * https://svn.boost.org/trac/boost/ticket/3076 + */ + { + Sequence ss3; + sequenced_index &si3=get<1>(ss3); + si3.sort(); + } +} + +template<typename Sequence> +static void test_list_ops_non_unique_seq() +{ + typedef typename Sequence::iterator iterator; + + Sequence ss; + for(int i=0;i<10;++i){ + ss.push_back(i); + ss.push_back(i); + ss.push_front(i); + ss.push_front(i); + } /* 9988776655443322110000112233445566778899 */ + + ss.unique(); + CHECK_EQUAL( + ss, + (9)(8)(7)(6)(5)(4)(3)(2)(1)(0) + (1)(2)(3)(4)(5)(6)(7)(8)(9)); + + iterator it=ss.begin(); + for(int j=0;j<9;++j,++it){} /* it points to o */ + + Sequence ss2; + ss2.splice(ss2.end(),ss,ss.begin(),it); + ss2.reverse(); + ss.merge(ss2); + CHECK_EQUAL( + ss, + (0)(1)(1)(2)(2)(3)(3)(4)(4)(5)(5) + (6)(6)(7)(7)(8)(8)(9)(9)); + + ss.unique(same_integral_div<3>()); + CHECK_EQUAL(ss,(0)(3)(6)(9)); + + ss.unique(same_integral_div<1>()); + CHECK_EQUAL(ss,(0)(3)(6)(9)); + + /* testcases for bugs reported at + * http://lists.boost.org/boost-users/2006/09/22604.php + */ + { + Sequence ss_,ss2_; + ss_.push_back(0); + ss2_.push_back(0); + ss_.splice(ss_.end(),ss2_,ss2_.begin()); + CHECK_EQUAL(ss_,(0)(0)); + BOOST_TEST(ss2_.empty()); + + ss_.clear(); + ss2_.clear(); + ss_.push_back(0); + ss2_.push_back(0); + ss_.splice(ss_.end(),ss2_,ss2_.begin(),ss2_.end()); + CHECK_EQUAL(ss_,(0)(0)); + BOOST_TEST(ss2_.empty()); + + ss_.clear(); + ss2_.clear(); + ss_.push_back(0); + ss2_.push_back(0); + ss_.merge(ss2_); + CHECK_EQUAL(ss_,(0)(0)); + BOOST_TEST(ss2_.empty()); + + typedef typename Sequence::value_type value_type; + ss_.clear(); + ss2_.clear(); + ss_.push_back(0); + ss2_.push_back(0); + ss_.merge(ss2_,std::less<value_type>()); + CHECK_EQUAL(ss_,(0)(0)); + BOOST_TEST(ss2_.empty()); + } +} + +#if BOOST_WORKAROUND(__MWERKS__,<=0x3003) +#pragma parse_func_templ reset +#endif + +void test_list_ops() +{ + typedef multi_index_container< + int, + indexed_by< + ordered_unique<identity<int> >, + sequenced<> + > + > sequenced_set; + + test_list_ops_unique_seq<sequenced_set>(); + + + typedef multi_index_container< + int, + indexed_by< + ordered_unique<identity<int> >, + random_access<> + > + > random_access_set; + + test_list_ops_unique_seq<random_access_set>(); + + typedef multi_index_container< + int, + indexed_by<sequenced<> > + > int_list; + + test_list_ops_non_unique_seq<int_list>(); + + typedef multi_index_container< + int, + indexed_by<random_access<> > + > int_vector; + + test_list_ops_non_unique_seq<int_vector>(); +} diff --git a/src/boost/libs/multi_index/test/test_list_ops.hpp b/src/boost/libs/multi_index/test/test_list_ops.hpp new file mode 100644 index 000000000..4547c88a6 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_list_ops.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for standard list operations. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_list_ops(); diff --git a/src/boost/libs/multi_index/test/test_list_ops_main.cpp b/src/boost/libs/multi_index/test/test_list_ops_main.cpp new file mode 100644 index 000000000..ce79320a0 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_list_ops_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for standard list operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_list_ops.hpp" + +int main() +{ + test_list_ops(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_modifiers.cpp b/src/boost/libs/multi_index/test/test_modifiers.cpp new file mode 100644 index 000000000..ea677ae15 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_modifiers.cpp @@ -0,0 +1,581 @@ +/* Boost.MultiIndex test for modifier memfuns. + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +#include "test_modifiers.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/detail/lightweight_test.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/iterator/iterator_facade.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/next_prior.hpp> +#include <boost/shared_ptr.hpp> +#include <iterator> +#include <vector> +#include "pre_multi_index.hpp" +#include "employee.hpp" + +using namespace boost::multi_index; + +struct non_copyable_int +{ + explicit non_copyable_int(int n_):n(n_){} + non_copyable_int(BOOST_RV_REF(non_copyable_int) x):n(x.n){x.n=0;} + non_copyable_int& operator=(BOOST_RV_REF(non_copyable_int) x) + { + n=x.n; + x.n=0; + return *this; + } + + int n; +private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(non_copyable_int) +}; + +class always_one +{ +public: + always_one():n(1){} + ~always_one(){n=0;} + + int get()const{return n;} + +private: + int n; +}; + +inline bool operator==(const always_one& x,const always_one& y) +{ + return x.get()==y.get(); +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +namespace boost{ +#endif + +inline std::size_t hash_value(const always_one& x) +{ + return static_cast<std::size_t>(x.get()); +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +} /* namespace boost */ +#endif + +class linked_object +{ + struct impl:boost::enable_shared_from_this<impl> + { + typedef boost::shared_ptr<const impl> ptr; + + impl(int n_,ptr next_=ptr()):n(n_),next(next_){} + + int n; + ptr next; + }; + + typedef multi_index_container< + impl, + indexed_by< + +#if BOOST_WORKAROUND(__IBMCPP__,BOOST_TESTED_AT(1010)) + ordered_unique<member<impl,int,&linked_object::impl::n> >, + hashed_non_unique<member<impl,int,&linked_object::impl::n> >, +#else + ordered_unique<member<impl,int,&impl::n> >, + hashed_non_unique<member<impl,int,&impl::n> >, +#endif + + sequenced<>, + random_access<> + > + > impl_repository_t; + + static impl_repository_t impl_repository; + +public: + linked_object(int n):pimpl(init(impl(n))){} + linked_object(int n,const linked_object& x):pimpl(init(impl(n,x.pimpl))){} + +private: + impl::ptr init(const impl& x) + { + std::pair<impl_repository_t::iterator,bool> p=impl_repository.insert(x); + if(p.second)return impl::ptr(&*p.first,&erase_impl); + else return p.first->shared_from_this(); + } + + static void erase_impl(const impl* p) + { + impl_repository.erase(p->n); + } + + impl::ptr pimpl; +}; + +linked_object::impl_repository_t linked_object::impl_repository; + +struct tempvalue_iterator: + boost::iterator_facade< + tempvalue_iterator,int,boost::forward_traversal_tag,int> +{ + tempvalue_iterator(int n_):n(n_){} + + void increment(){++n;} + bool equal(const tempvalue_iterator& x)const{return n==x.n;} + int dereference()const{return n;} + + int n; +}; + +struct change_int +{ + change_int(int n):n(n){} + + void operator()(int& x)const{x=n;} + + int n; +}; + +#if !(defined BOOST_NO_EXCEPTIONS) +struct change_int_and_throw +{ + change_int_and_throw(int n):n(n){} + + void operator()(int& x)const{x=n;throw 0;} + + int n; +}; +#endif + +void test_modifiers() +{ + employee_set es; + employee_set_by_name& i1=get<name>(es); + employee_set_by_age& i2=get<age>(es); + employee_set_as_inserted& i3=get<as_inserted>(es); + employee_set_by_ssn& i4=get<ssn>(es); + employee_set_randomly& i5=get<randomly>(es); + + es.insert(employee(0,"Joe",31,1123)); + BOOST_TEST(es.emplace(0,"Joe",31,1123).second==false); + BOOST_TEST(i1.insert(employee(0,"Joe Jr.",5,2563)).second==false); + BOOST_TEST(i2.emplace_hint(i2.end(),1,"Victor",5,1123)->name!="Victor"); + BOOST_TEST(i3.insert(i3.begin(),employee(1,"Victor",5,1123)).second + ==false); + BOOST_TEST(i3.push_front(employee(0,"Joe Jr.",5,2563)).second==false); + BOOST_TEST(i3.push_back(employee(0,"Joe Jr.",5,2563)).second==false); + BOOST_TEST(i5.emplace_front(1,"Victor",5,1123).second==false); + BOOST_TEST(i5.emplace_back(1,"Victor",5,1123).second==false); + + employee_set_by_name::iterator it1=i1.find("Joe"); + i1.insert(it1,employee(1,"Joe Jr.",5,2563)); + BOOST_TEST(es.size()==2); + + employee_set_by_age::iterator it2=i2.find(31); + i2.insert(it2,employee(2,"Grandda Joe",64,7881)); + BOOST_TEST(es.size()==3); + + employee_set_as_inserted::iterator it3=i3.begin(); + i3.insert(it3,100,employee(3,"Judy",39,6201)); + BOOST_TEST((--it3)->ssn==6201); + BOOST_TEST(es.size()==4); + + employee_set_randomly::iterator it5=i5.begin(); + i5.insert(it5,100,employee(4,"Jill",52,3379)); + BOOST_TEST(i5.begin()->age==52); + BOOST_TEST(es.size()==5); + + es.erase(employee(1,"Joe Jr.",5,2563)); + BOOST_TEST(i3.size()==4&&i5.size()==4); + + BOOST_TEST(i1.erase("Judy")==1); + BOOST_TEST(es.size()==3&&i2.size()==3); + + BOOST_TEST(i2.erase(it2)->age==52); + BOOST_TEST(i3.size()==2&&i4.size()==2); + + i3.pop_front(); + BOOST_TEST(i1.size()==1&&i2.size()==1); + + i5.erase(i5.begin(),i5.end()); + BOOST_TEST(es.size()==0&&i3.size()==0); + + i5.emplace(i5.end(),0,"Joe",31,1123); + BOOST_TEST(i1.erase(i1.begin())==i1.end()); + BOOST_TEST(i1.size()==0); + + i1.emplace(0,"Joe",31,1123); + i3.emplace(i3.begin(),1,"Jack",31,5032); + i4.emplace_hint(i4.end(),2,"James",31,3847); + BOOST_TEST(i2.erase(31)==3); + BOOST_TEST(i2.size()==0); + + i3.emplace_front(1,"Jack",31,5032); + i3.emplace_back(0,"Joe",31,1123); + BOOST_TEST(i3.front()==employee(1,"Jack",31,5032)); + BOOST_TEST(i3.back()==employee(0,"Joe",31,1123)); + + i3.pop_back(); + BOOST_TEST(i3.back()==employee(1,"Jack",31,5032)); + BOOST_TEST(es.size()==1); + + i3.pop_front(); + BOOST_TEST(es.size()==0); + + i5.push_back(employee(1,"Jack",31,5032)); + i5.push_front(employee(0,"Joe",31,1123)); + i5.insert(i5.end()-1,employee(2,"Grandda Joe",64,7881)); + BOOST_TEST(i5.back()==employee(1,"Jack",31,5032)); + BOOST_TEST(i5.front()==employee(0,"Joe",31,1123)); + BOOST_TEST(i5[0]==i5.front()&&i5.at(0)==i5.front()); + BOOST_TEST(i5[i5.size()-1]==i5.back()&&i5.at(i5.size()-1)==i5.back()); + + i5.pop_front(); + BOOST_TEST(i5.back()==employee(1,"Jack",31,5032)); + BOOST_TEST(i5.front()==employee(2,"Grandda Joe",64,7881)); + BOOST_TEST(es.size()==2); + + i5.pop_back(); + BOOST_TEST(i5.back()==employee(2,"Grandda Joe",64,7881)); + BOOST_TEST(i5.front()==i5.front()); + BOOST_TEST(es.size()==1); + + i5.erase(i5.begin()); + BOOST_TEST(es.size()==0); + + std::vector<employee> ve; + ve.push_back(employee(3,"Anna",31,5388)); + ve.push_back(employee(1,"Rachel",27,9012)); + ve.push_back(employee(2,"Agatha",40,1520)); + + i1.insert(ve.begin(),ve.end()); + BOOST_TEST(i2.size()==3); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + i1.insert({{4,"Vanessa",20,9236},{5,"Penelope",55,2358}}); + BOOST_TEST(i2.size()==5); +#endif + + BOOST_TEST(i2.erase(i2.begin(),i2.end())==i2.end()); + BOOST_TEST(es.size()==0); + + i2.insert(ve.begin(),ve.end()); + BOOST_TEST(i3.size()==3); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + i2.insert({{4,"Vanessa",20,9236},{5,"Penelope",55,2358}}); + BOOST_TEST(i3.size()==5); +#endif + + BOOST_TEST(*(i3.erase(i3.begin()))==employee(1,"Rachel",27,9012)); + BOOST_TEST(i3.erase(i3.begin(),i3.end())==i3.end()); + BOOST_TEST(es.size()==0); + + i3.insert(i3.end(),ve.begin(),ve.end()); + BOOST_TEST(es.size()==3); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + i3.insert(i3.begin(),{{4,"Vanessa",20,9236},{5,"Penelope",55,2358}}); + BOOST_TEST(i3.front().name=="Vanessa"); + BOOST_TEST(i4.size()==5); +#endif + + BOOST_TEST(i4.erase(9012)==1); + i4.erase(i4.begin()); + BOOST_TEST(i4.erase(i4.begin(),i4.end())==i4.end()); + + i4.insert(ve.begin(),ve.end()); + BOOST_TEST(i5.size()==3); + + BOOST_TEST(i5.erase(i5.begin(),i5.end())==i5.end()); + BOOST_TEST(es.size()==0); + + i5.insert(i5.begin(),ve.begin(),ve.end()); + BOOST_TEST(i1.size()==3); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + i5.insert(i5.end(),{{4,"Vanessa",20,9236},{5,"Penelope",55,2358}}); + BOOST_TEST(i5.back().name=="Penelope"); + BOOST_TEST(i1.size()==5); +#endif + + BOOST_TEST(es.erase(es.begin(),es.end())==es.end()); + BOOST_TEST(i2.size()==0); + + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + es.insert(employee(3,"Albert",20,9012)); + es.insert(employee(4,"John",57,1002)); + + employee_set es_backup(es); + + employee_set es2; + es2.insert(employee(3,"Anna",31,5388)); + es2.insert(employee(1,"Rachel",27,9012)); + es2.insert(employee(2,"Agatha",40,1520)); + + employee_set es2_backup(es2); + + i1.swap(get<1>(es2)); + BOOST_TEST(es==es2_backup&&es2==es_backup); + + i2.swap(get<2>(es2)); + BOOST_TEST(es==es_backup&&es2==es2_backup); + + i3.swap(get<3>(es2)); + BOOST_TEST(es==es2_backup&&es2==es_backup); + + i4.swap(get<4>(es2)); + BOOST_TEST(es==es_backup&&es2==es2_backup); + + i5.swap(get<5>(es2)); + BOOST_TEST(es==es2_backup&&es2==es_backup); + +#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) + ::boost::multi_index::detail::swap(i1,get<1>(es2)); +#else + using std::swap; + swap(i1,get<1>(es2)); +#endif + + BOOST_TEST(es==es_backup&&es2==es2_backup); + +#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) + ::boost::multi_index::detail::swap(i2,get<2>(es2)); +#else + using std::swap; + swap(i2,get<2>(es2)); +#endif + + BOOST_TEST(es==es2_backup&&es2==es_backup); + +#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) + ::boost::multi_index::detail::swap(i3,get<3>(es2)); +#else + using std::swap; + swap(i3,get<3>(es2)); +#endif + + BOOST_TEST(es==es_backup&&es2==es2_backup); + +#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) + ::boost::multi_index::detail::swap(i4,get<4>(es2)); +#else + using std::swap; + swap(i4,get<4>(es2)); +#endif + + BOOST_TEST(es==es2_backup&&es2==es_backup); + +#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) + ::boost::multi_index::detail::swap(i5,get<5>(es2)); +#else + using std::swap; + swap(i5,get<5>(es2)); +#endif + + BOOST_TEST(es==es_backup&&es2==es2_backup); + + i3.clear(); + BOOST_TEST(i3.size()==0); + + es=es2; + i4.clear(); + BOOST_TEST(i4.size()==0); + + es=es2; + i5.clear(); + BOOST_TEST(i5.size()==0); + + es2.clear(); + BOOST_TEST(es2.size()==0); + + /* non-copyable elements */ + + multi_index_container< + non_copyable_int, + indexed_by< + ordered_non_unique<member<non_copyable_int,int,&non_copyable_int::n> >, + hashed_non_unique<member<non_copyable_int,int,&non_copyable_int::n> >, + sequenced<>, + random_access<> + > + > ncic,ncic2; + + ncic.emplace(1); + get<1>(ncic).emplace(1); + get<2>(ncic).emplace_back(1); + get<3>(ncic).emplace_back(1); + + non_copyable_int nci(1); + ncic.insert(boost::move(nci)); + BOOST_TEST(nci.n==0); + + nci.n=1; + get<1>(ncic).insert(boost::move(nci)); + BOOST_TEST(nci.n==0); + + nci.n=1; + get<2>(ncic).push_back(boost::move(nci)); + BOOST_TEST(nci.n==0); + + nci.n=1; + get<3>(ncic).push_back(boost::move(nci)); + BOOST_TEST(nci.n==0); + + std::vector<int> vi(4,1); + const std::vector<int>& cvi=vi; + ncic.insert(vi.begin(),vi.end()); + ncic.insert(cvi.begin(),cvi.end()); + get<2>(ncic).insert(get<2>(ncic).begin(),vi.begin(),vi.end()); + get<2>(ncic).insert(get<2>(ncic).begin(),cvi.begin(),cvi.end()); + + BOOST_TEST(ncic.count(1)==24); + + ncic.swap(ncic2); + BOOST_TEST(ncic.empty()); + BOOST_TEST(ncic2.count(1)==24); + + /* testcase for problem reported at + * http://lists.boost.org/boost-users/2006/12/24215.php + */ + + multi_index_container< + always_one, + indexed_by< + hashed_non_unique<identity<always_one> > + > + > aoc; + + aoc.insert(always_one()); + aoc.insert(always_one()); + aoc.erase(*(aoc.begin())); + BOOST_TEST(aoc.empty()); + + /* Testcases for compliance with "as close to hint as possible" + * proposed behavior for associative containers: + * http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233 + * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html + */ + + typedef multi_index_container< + int, + indexed_by< + ordered_non_unique<identity<int> > + > + > int_non_unique_container; + + int_non_unique_container c; + c.insert(0);c.insert(0); + c.insert(1);c.insert(1); + c.insert(2);c.insert(2); + + BOOST_TEST(std::distance(c.begin(),c.insert(c.begin(),1))==2); + BOOST_TEST(std::distance(c.begin(),c.insert(boost::next(c.begin()),1))==2); + BOOST_TEST(std::distance(c.begin(),c.insert(c.lower_bound(1),1))==2); + BOOST_TEST( + std::distance(c.begin(),c.insert(boost::next(c.lower_bound(1)),1))==3); + BOOST_TEST(std::distance(c.begin(),c.insert(c.upper_bound(1),1))==8); + BOOST_TEST(std::distance(c.begin(),c.insert(boost::prior(c.end()),1))==9); + BOOST_TEST(std::distance(c.begin(),c.insert(c.end(),1))==10); + + /* testcase for erase() reentrancy */ + { + linked_object o1(1); + linked_object o2(2,o1); + o1=o2; + } + + /* testcases for bug reported at + * https://svn.boost.org/trac/boost/ticket/9665 + */ + + { + multi_index_container< + int, + indexed_by<hashed_unique<identity<int> > > + > hc; + hc.insert(tempvalue_iterator(0),tempvalue_iterator(10)); + BOOST_TEST(hc.size()==10); + + multi_index_container< + int, + indexed_by<ordered_unique<identity<int> > > + > oc; + oc.insert(tempvalue_iterator(0),tempvalue_iterator(10)); + BOOST_TEST(oc.size()==10); + } + + /* testcases for https://svn.boost.org/trac10/ticket/12542 */ + + { + multi_index_container< + int, + indexed_by< + ordered_unique<identity<int> >, + hashed_unique<identity<int> > + > + > ohc; + +#if !(defined BOOST_NO_EXCEPTIONS) + ohc.insert(0); + ohc.insert(1); + + try{ + ohc.modify_key(ohc.begin(),change_int_and_throw(1)); + } + catch(int){} + BOOST_TEST(ohc.size()==1); + ohc.clear(); + + ohc.insert(0); + ohc.insert(1); + + try{ + ohc.modify_key(ohc.begin(),change_int_and_throw(1),change_int(0)); + } + catch(int){} + BOOST_TEST(ohc.size()==1); + ohc.clear(); + + ohc.insert(0); + ohc.insert(1); + + try{ + ohc.modify_key( + ohc.begin(),change_int_and_throw(1),change_int_and_throw(0)); + } + catch(int){} + BOOST_TEST(ohc.size()==1); + ohc.clear(); + + ohc.insert(0); + ohc.insert(1); + + try{ + ohc.modify_key(ohc.begin(),change_int(1),change_int_and_throw(0)); + } + catch(int){} + BOOST_TEST(ohc.size()==1); + ohc.clear(); +#endif + + ohc.insert(0); + ohc.insert(1); + + ohc.modify_key(ohc.begin(),change_int(1),change_int(1)); + BOOST_TEST(ohc.size()==1); + ohc.clear(); + } +} diff --git a/src/boost/libs/multi_index/test/test_modifiers.hpp b/src/boost/libs/multi_index/test/test_modifiers.hpp new file mode 100644 index 000000000..c5d28f818 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_modifiers.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for modifier memfuns. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_modifiers(); diff --git a/src/boost/libs/multi_index/test/test_modifiers_main.cpp b/src/boost/libs/multi_index/test/test_modifiers_main.cpp new file mode 100644 index 000000000..795289f87 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_modifiers_main.cpp @@ -0,0 +1,20 @@ +/* Boost.MultiIndex test for modifier memfuns. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_modifiers.hpp" + +int main() +{ + test_modifiers(); + return boost::report_errors(); +} + + diff --git a/src/boost/libs/multi_index/test/test_mpl_ops.cpp b/src/boost/libs/multi_index/test/test_mpl_ops.cpp new file mode 100644 index 000000000..21b86072f --- /dev/null +++ b/src/boost/libs/multi_index/test/test_mpl_ops.cpp @@ -0,0 +1,75 @@ +/* Boost.MultiIndex test for MPL operations. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#include "test_mpl_ops.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include "pre_multi_index.hpp" +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/mpl/at.hpp> +#include <boost/mpl/list.hpp> + +using namespace boost::multi_index; + +void test_mpl_ops() +{ + typedef multi_index_container< + int, + indexed_by< + ordered_unique<identity<int> >, + ordered_non_unique<identity<int> > + > + > indexed_t1; + + BOOST_STATIC_ASSERT((boost::is_same< + boost::mpl::at_c<indexed_t1::index_specifier_type_list,0>::type, + ordered_unique<identity<int> > >::value)); + BOOST_STATIC_ASSERT((boost::is_same< + boost::mpl::at_c<indexed_t1::index_specifier_type_list,1>::type, + ordered_non_unique<identity<int> > >::value)); + + typedef boost::mpl::push_front< + indexed_t1::index_specifier_type_list, + sequenced<> + >::type index_list_t; + + typedef multi_index_container< + int, + index_list_t + > indexed_t2; + + BOOST_STATIC_ASSERT((boost::is_same< + boost::mpl::at_c<indexed_t2::index_specifier_type_list,0>::type, + sequenced<> >::value)); + BOOST_STATIC_ASSERT((boost::is_same< + boost::mpl::at_c<indexed_t2::index_specifier_type_list,1>::type, + boost::mpl::at_c<indexed_t1::index_specifier_type_list,0>::type>::value)); + BOOST_STATIC_ASSERT((boost::is_same< + boost::mpl::at_c<indexed_t2::index_specifier_type_list,2>::type, + boost::mpl::at_c<indexed_t1::index_specifier_type_list,1>::type>::value)); + + typedef multi_index_container< + int, + boost::mpl::list< + ordered_unique<identity<int> >, + ordered_non_unique<identity<int> > + > + > indexed_t3; + + BOOST_STATIC_ASSERT((boost::is_same< + boost::mpl::at_c<indexed_t3::index_specifier_type_list,0>::type, + boost::mpl::at_c<indexed_t1::index_specifier_type_list,0>::type>::value)); + BOOST_STATIC_ASSERT((boost::is_same< + boost::mpl::at_c<indexed_t3::index_specifier_type_list,1>::type, + boost::mpl::at_c<indexed_t1::index_specifier_type_list,1>::type>::value)); +} diff --git a/src/boost/libs/multi_index/test/test_mpl_ops.hpp b/src/boost/libs/multi_index/test/test_mpl_ops.hpp new file mode 100644 index 000000000..320600bac --- /dev/null +++ b/src/boost/libs/multi_index/test/test_mpl_ops.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for for MPL operations. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_mpl_ops(); diff --git a/src/boost/libs/multi_index/test/test_mpl_ops_main.cpp b/src/boost/libs/multi_index/test/test_mpl_ops_main.cpp new file mode 100644 index 000000000..fe1879b25 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_mpl_ops_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for for MPL operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_mpl_ops.hpp" + +int main() +{ + test_mpl_ops(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_observers.cpp b/src/boost/libs/multi_index/test/test_observers.cpp new file mode 100644 index 000000000..8013408a4 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_observers.cpp @@ -0,0 +1,56 @@ +/* Boost.MultiIndex test for observer memfuns. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include "test_observers.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <vector> +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +void test_observers() +{ + employee_set es; + const employee_set_by_name& i1=get<by_name>(es); + const employee_set_by_age& i2=get<age>(es); + + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + es.insert(employee(3,"Albert",20,9012)); + es.insert(employee(4,"John",57,1002)); + + { + employee_set_by_name::key_from_value k=i1.key_extractor(); + employee_set_by_name::hasher h=i1.hash_function(); + employee_set_by_name::key_equal eq=i1.key_eq(); + + employee_set_by_name::const_iterator it0=i1.equal_range("John").first; + employee_set_by_name::const_iterator it1=it0;++it1; + BOOST_TEST(k(*it0)=="John"&&k(*it1)=="John"); + BOOST_TEST(h(k(*it0))==h(k(*it1))); + BOOST_TEST(eq(k(*it0),k(*it1))==true); + } + { + employee_set_by_age::key_from_value k=i2.key_extractor(); + employee_set_by_age::key_compare c=i2.key_comp(); + employee_set_by_age::value_compare vc=i2.value_comp(); + + employee_set_by_age::const_iterator it0=i2.find(31); + employee_set_by_age::const_iterator it1=i2.find(40); + BOOST_TEST(k(*it0)==31&&k(*it1)==40); + BOOST_TEST(c(k(*it0),k(*it1))==true); + BOOST_TEST(vc(*it0,*it1)==true); + } +} diff --git a/src/boost/libs/multi_index/test/test_observers.hpp b/src/boost/libs/multi_index/test/test_observers.hpp new file mode 100644 index 000000000..f9a0a1129 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_observers.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for observer memfuns. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_observers(); diff --git a/src/boost/libs/multi_index/test/test_observers_main.cpp b/src/boost/libs/multi_index/test/test_observers_main.cpp new file mode 100644 index 000000000..2d92fe626 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_observers_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for observer memfuns. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_observers.hpp" + +int main() +{ + test_observers(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_projection.cpp b/src/boost/libs/multi_index/test/test_projection.cpp new file mode 100644 index 000000000..324a04583 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_projection.cpp @@ -0,0 +1,135 @@ +/* Boost.MultiIndex test for projection capabilities. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include "test_projection.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +void test_projection() +{ + employee_set es; + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + es.insert(employee(3,"Albert",20,9012)); + es.insert(employee(4,"John",57,1002)); + + employee_set::iterator it,itbis; + employee_set_by_name::iterator it1; + employee_set_by_age::iterator it2; + employee_set_as_inserted::iterator it3; + employee_set_by_ssn::iterator it4; + employee_set_randomly::iterator it5; + + BOOST_STATIC_ASSERT((boost::is_same< + employee_set::iterator, + nth_index_iterator<employee_set,0>::type >::value)); + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_by_name::iterator, + nth_index_iterator<employee_set,1>::type >::value)); +#if defined(BOOST_NO_MEMBER_TEMPLATES) + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_by_age::iterator, + index_iterator<employee_set,age>::type >::value)); +#else + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_by_age::iterator, + employee_set::index_iterator<age>::type >::value)); +#endif + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_as_inserted::iterator, + nth_index_iterator<employee_set,3>::type >::value)); + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_by_ssn::iterator, + nth_index_iterator<employee_set,4>::type >::value)); + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_randomly::iterator, + nth_index_iterator<employee_set,5>::type >::value)); + + it= es.find(employee(1,"Robert",27,5601)); + it1= project<name>(es,it); + it2= project<age>(es,it1); + it3= project<as_inserted>(es,it2); + it4= project<ssn>(es,it3); + it5= project<randomly>(es,it4); +#if defined(BOOST_NO_MEMBER_TEMPLATES) + itbis=project<0>(es,it5); +#else + itbis=es.project<0>(it5); +#endif + + BOOST_TEST( + *it==*it1&&*it1==*it2&&*it2==*it3&&*it3==*it4&&*it4==*it5&&itbis==it); + + BOOST_TEST(project<name>(es,es.end())==get<name>(es).end()); + BOOST_TEST(project<age>(es,es.end())==get<age>(es).end()); + BOOST_TEST(project<as_inserted>(es,es.end())==get<as_inserted>(es).end()); + BOOST_TEST(project<ssn>(es,es.end())==get<ssn>(es).end()); + BOOST_TEST(project<randomly>(es,es.end())==get<randomly>(es).end()); + + const employee_set& ces=es; + + employee_set::const_iterator cit,citbis; + employee_set_by_name::const_iterator cit1; + employee_set_by_age::const_iterator cit2; + employee_set_as_inserted::const_iterator cit3; + employee_set_by_ssn::const_iterator cit4; + employee_set_randomly::const_iterator cit5; + + BOOST_STATIC_ASSERT((boost::is_same< + employee_set::const_iterator, + nth_index_const_iterator<employee_set,0>::type >::value)); + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_by_name::const_iterator, + nth_index_const_iterator<employee_set,1>::type >::value)); +#if defined(BOOST_NO_MEMBER_TEMPLATES) + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_by_age::const_iterator, + index_const_iterator<employee_set,age>::type >::value)); +#else + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_by_age::const_iterator, + employee_set::index_const_iterator<age>::type >::value)); +#endif + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_as_inserted::const_iterator, + nth_index_const_iterator<employee_set,3>::type >::value)); + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_by_ssn::const_iterator, + nth_index_const_iterator<employee_set,4>::type >::value)); + BOOST_STATIC_ASSERT((boost::is_same< + employee_set_randomly::const_iterator, + nth_index_const_iterator<employee_set,5>::type >::value)); + + cit= ces.find(employee(4,"John",57,1002)); +#if defined(BOOST_NO_MEMBER_TEMPLATES) + cit1= project<by_name>(ces,cit); +#else + cit1= ces.project<by_name>(cit); +#endif + cit2= project<age>(ces,cit1); +#if defined(BOOST_NO_MEMBER_TEMPLATES) + cit3= project<as_inserted>(ces,cit2); +#else + cit3= ces.project<as_inserted>(cit2); +#endif + cit4= project<ssn>(ces,cit3); + cit5= project<randomly>(ces,cit4); + citbis=project<0>(ces,cit5); + + BOOST_TEST( + *cit==*cit1&&*cit1==*cit2&&*cit2==*cit3&&*cit3==*cit4&&*cit4==*cit5&& + citbis==cit); +} diff --git a/src/boost/libs/multi_index/test/test_projection.hpp b/src/boost/libs/multi_index/test/test_projection.hpp new file mode 100644 index 000000000..660ecb232 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_projection.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for projection capabilities. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_projection(); diff --git a/src/boost/libs/multi_index/test/test_projection_main.cpp b/src/boost/libs/multi_index/test/test_projection_main.cpp new file mode 100644 index 000000000..560316a65 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_projection_main.cpp @@ -0,0 +1,20 @@ +/* Boost.MultiIndex test for projection capabilities. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_projection.hpp" + +int main() +{ + test_projection(); + return boost::report_errors(); +} + + diff --git a/src/boost/libs/multi_index/test/test_range.cpp b/src/boost/libs/multi_index/test/test_range.cpp new file mode 100644 index 000000000..0d6ab13a3 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_range.cpp @@ -0,0 +1,125 @@ +/* Boost.MultiIndex test for range(). + * + * Copyright 2003-2020 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/multi_index for library home page. + */ + +#include "test_range.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <boost/bind/bind.hpp> +#include <boost/detail/lightweight_test.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/preprocessor/seq/enum.hpp> +#include <functional> + +using namespace boost::multi_index; + +typedef multi_index_container<int> int_set; +typedef int_set::iterator int_set_iterator; + +#undef CHECK_RANGE +#define CHECK_RANGE(p,check_seq) \ +{\ + int v[]={BOOST_PP_SEQ_ENUM(check_seq)};\ + std::size_t size_v=sizeof(v)/sizeof(int);\ + BOOST_TEST(std::size_t(std::distance((p).first,(p).second))==size_v);\ + BOOST_TEST(std::equal((p).first,(p).second,&v[0]));\ +} + +#undef CHECK_VOID_RANGE +#define CHECK_VOID_RANGE(p) BOOST_TEST((p).first==(p).second) + +#undef BIND1ST +#define BIND1ST(f,x) ::boost::bind(f,x,::boost::arg<1>()) + +#undef BIND2ND +#define BIND2ND(f,x) ::boost::bind(f,::boost::arg<1>(),x) + +void test_range() +{ + int_set is; + + for(int i=1;i<=10;++i)is.insert(i); + + std::pair<int_set::iterator,int_set::iterator> p; + + p=is.range(unbounded,unbounded); + CHECK_RANGE(p,(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)); + + p=is.range( + BIND1ST(std::less<int>(),5), /* 5 < x */ + unbounded); + CHECK_RANGE(p,(6)(7)(8)(9)(10)); + + p=is.range( + BIND1ST(std::less_equal<int>(),8), /* 8 <= x */ + unbounded); + CHECK_RANGE(p,(8)(9)(10)); + + p=is.range( + BIND1ST(std::less_equal<int>(),11), /* 11 <= x */ + unbounded); + CHECK_VOID_RANGE(p); + + p=is.range( + unbounded, + BIND2ND(std::less<int>(),8)); /* x < 8 */ + CHECK_RANGE(p,(1)(2)(3)(4)(5)(6)(7)); + + p=is.range( + unbounded, + BIND2ND(std::less_equal<int>(),4)); /* x <= 4 */ + CHECK_RANGE(p,(1)(2)(3)(4)); + + p=is.range( + unbounded, + BIND2ND(std::less_equal<int>(),0)); /* x <= 0 */ + CHECK_VOID_RANGE(p); + + p=is.range( + BIND1ST(std::less<int>(),6), /* 6 < x */ + BIND2ND(std::less_equal<int>(),9)); /* x <= 9 */ + CHECK_RANGE(p,(7)(8)(9)); + + p=is.range( + BIND1ST(std::less_equal<int>(),4), /* 4 <= x */ + BIND2ND(std::less<int>(),5)); /* x < 5 */ + CHECK_RANGE(p,(4)); + + p=is.range( + BIND1ST(std::less_equal<int>(),10), /* 10 <= x */ + BIND2ND(std::less_equal<int>(),10)); /* x <= 10 */ + CHECK_RANGE(p,(10)); + + p=is.range( + BIND1ST(std::less<int>(),0), /* 0 < x */ + BIND2ND(std::less<int>(),11)); /* x < 11 */ + CHECK_RANGE(p,(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)); + + p=is.range( + BIND1ST(std::less<int>(),7), /* 7 < x */ + BIND2ND(std::less_equal<int>(),7)); /* x <= 7 */ + CHECK_VOID_RANGE(p); + BOOST_TEST(p.first==is.upper_bound(7)); + + p=is.range( + BIND1ST(std::less_equal<int>(),8), /* 8 <= x */ + BIND2ND(std::less<int>(),2)); /* x < 2 */ + CHECK_VOID_RANGE(p); + BOOST_TEST(p.first==is.lower_bound(8)); + + p=is.range( + BIND1ST(std::less<int>(),4), /* 4 < x */ + BIND2ND(std::less<int>(),5)); /* x < 5 */ + CHECK_VOID_RANGE(p); + BOOST_TEST(p.first!=is.end()); +} diff --git a/src/boost/libs/multi_index/test/test_range.hpp b/src/boost/libs/multi_index/test/test_range.hpp new file mode 100644 index 000000000..2706e8dbd --- /dev/null +++ b/src/boost/libs/multi_index/test/test_range.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for range(). + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_range(); diff --git a/src/boost/libs/multi_index/test/test_range_main.cpp b/src/boost/libs/multi_index/test/test_range_main.cpp new file mode 100644 index 000000000..8c916687c --- /dev/null +++ b/src/boost/libs/multi_index/test/test_range_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for range(). + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_range.hpp" + +int main() +{ + test_range(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_rank_ops.cpp b/src/boost/libs/multi_index/test/test_rank_ops.cpp new file mode 100644 index 000000000..670540143 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_rank_ops.cpp @@ -0,0 +1,154 @@ +/* Boost.MultiIndex test for rank operations. + * + * Copyright 2003-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/multi_index for library home page. + */ + +#include "test_rank_ops.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <iterator> +#include <set> +#include <boost/detail/lightweight_test.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/identity.hpp> +#include <boost/multi_index/ranked_index.hpp> + +using namespace boost::multi_index; + +template< + typename Sequence1,typename Iterator2,typename Sequence2 +> +bool same_position( + std::size_t n1,const Sequence1& s1,Iterator2 it2,const Sequence2& s2) +{ + typedef typename Sequence1::const_iterator const_iterator1; + typedef typename Sequence2::const_iterator const_iterator2; + + const_iterator1 cit1=s1.begin(); + std::advance(cit1,n1); + const_iterator2 cit2=it2; + return std::distance(s1.begin(),cit1)==std::distance(s2.begin(),cit2); +} + +struct less_equal_than +{ + less_equal_than(int n_):n(n_){} + bool operator()(int x)const{return x<=n;} + int n; +}; + +struct greater_equal_than +{ + greater_equal_than(int n_):n(n_){} + bool operator()(int x)const{return x>=n;} + int n; +}; + +template<typename Sequence> +static void local_test_rank_ops() +{ + int data[]={2,2,1,5,6,7,9,10,9,6,9,6,9}; + Sequence s(data,data+sizeof(data)/sizeof(data[0])); + std::multiset<int> ss(s.begin(),s.end()); + + typedef typename Sequence::iterator iterator; + + iterator it=s.begin(); + for(std::size_t n=0;n<=s.size()+1;++n){ + BOOST_TEST(s.nth(n)==it); + BOOST_TEST(s.rank(it)==(std::min)(s.size(),n)); + if(it!=s.end())++it; + } + + std::pair<std::size_t,std::size_t> p1; + std::pair<iterator,iterator> p2; + + p1=s.range_rank(unbounded,unbounded); + p2=s.range(unbounded,unbounded); + BOOST_TEST(same_position(p1.first,s,p2.first,s)); + BOOST_TEST(same_position(p1.second,s,p2.second,s)); + + for(int i=0;i<12;++i){ + std::size_t pos=s.find_rank(i); + BOOST_TEST((pos==s.size()&&ss.find(i)==ss.end())||(*s.nth(pos)==i)); + BOOST_TEST(same_position(s.lower_bound_rank(i),s,ss.lower_bound(i),ss)); + BOOST_TEST(same_position(s.upper_bound_rank(i),s,ss.upper_bound(i),ss)); + std::pair<std::size_t,std::size_t> posp=s.equal_range_rank(i); + BOOST_TEST(same_position(posp.first,s,ss.lower_bound(i),ss)); + BOOST_TEST(same_position(posp.second,s,ss.upper_bound(i),ss)); + + p1=s.range_rank(greater_equal_than(i),unbounded); + p2=s.range(greater_equal_than(i),unbounded); + BOOST_TEST(same_position(p1.first,s,p2.first,s)); + BOOST_TEST(same_position(p1.second,s,p2.second,s)); + p1=s.range_rank(unbounded,less_equal_than(i)); + p2=s.range(unbounded,less_equal_than(i)); + BOOST_TEST(same_position(p1.first,s,p2.first,s)); + BOOST_TEST(same_position(p1.second,s,p2.second,s)); + + for(int j=0;j<12;++j){ + p1=s.range_rank(greater_equal_than(i),less_equal_than(j)); + p2=s.range(greater_equal_than(i),less_equal_than(j)); + BOOST_TEST(same_position(p1.first,s,p2.first,s)); + BOOST_TEST(same_position(p1.second,s,p2.second,s)); + } + } + + Sequence se; /* empty */ + BOOST_TEST(se.nth(0)==se.end()); + BOOST_TEST(se.nth(1)==se.end()); + BOOST_TEST(se.rank(se.end())==0); + BOOST_TEST(se.find_rank(0)==0); + BOOST_TEST(se.lower_bound_rank(0)==0); + BOOST_TEST(se.upper_bound_rank(0)==0); + p1=se.equal_range_rank(0); + BOOST_TEST(p1.first==0&&p1.second==0); + p1=se.range_rank(unbounded,unbounded); + BOOST_TEST(p1.first==0&&p1.second==0); + p1=se.range_rank(greater_equal_than(0),unbounded); + BOOST_TEST(p1.first==0&&p1.second==0); + p1=se.range_rank(unbounded,less_equal_than(0)); + BOOST_TEST(p1.first==0&&p1.second==0); + p1=se.range_rank(greater_equal_than(0),less_equal_than(0)); + BOOST_TEST(p1.first==0&&p1.second==0); +} + +void test_rank_ops() +{ + typedef multi_index_container< + int, + indexed_by< + ranked_unique<identity<int> > + > + > ranked_set; + + local_test_rank_ops<ranked_set>(); + + typedef multi_index_container< + int, + indexed_by< + ranked_non_unique<identity<int> > + > + > ranked_multiset; + + local_test_rank_ops<ranked_multiset>(); + + /* testcase for https://svn.boost.org/trac/boost/ticket/12955 */ + + typedef multi_index_container< + int, + indexed_by< + ranked_unique<identity<int> >, + ranked_non_unique<identity<int> > + > + > biranked_set; + + local_test_rank_ops<biranked_set>(); +} diff --git a/src/boost/libs/multi_index/test/test_rank_ops.hpp b/src/boost/libs/multi_index/test/test_rank_ops.hpp new file mode 100644 index 000000000..d410bd6e3 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_rank_ops.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for rank operations. + * + * Copyright 2003-20015 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/multi_index for library home page. + */ + +void test_rank_ops(); diff --git a/src/boost/libs/multi_index/test/test_rank_ops_main.cpp b/src/boost/libs/multi_index/test/test_rank_ops_main.cpp new file mode 100644 index 000000000..b51de6be0 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_rank_ops_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for rank operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_rank_ops.hpp" + +int main() +{ + test_rank_ops(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_rearrange.cpp b/src/boost/libs/multi_index/test/test_rearrange.cpp new file mode 100644 index 000000000..9a5ddaec4 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_rearrange.cpp @@ -0,0 +1,132 @@ +/* Boost.MultiIndex test for rearrange operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include "test_rearrange.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <iterator> +#include <boost/detail/lightweight_test.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/multi_index/random_access_index.hpp> +#include <boost/next_prior.hpp> +#include <boost/preprocessor/seq/enum.hpp> +#include <boost/ref.hpp> +#include <vector> + +using namespace boost::multi_index; + +#undef CHECK_EQUAL +#define CHECK_EQUAL(p,check_seq) \ +{\ + int v[]={BOOST_PP_SEQ_ENUM(check_seq)};\ + std::size_t size_v=sizeof(v)/sizeof(int);\ + BOOST_TEST(std::size_t(std::distance((p).begin(),(p).end()))==size_v);\ + BOOST_TEST(std::equal((p).begin(),(p).end(),&v[0]));\ +} + +#undef CHECK_VOID_RANGE +#define CHECK_VOID_RANGE(p) BOOST_TEST((p).first==(p).second) + +#if BOOST_WORKAROUND(__MWERKS__,<=0x3003) +/* The "ISO C++ Template Parser" option makes CW8.3 incorrectly fail at + * expressions of the form sizeof(x) where x is an array local to a + * template function. + */ + +#pragma parse_func_templ off +#endif + +template<typename Sequence> +static void local_test_rearrange() +{ + typedef typename Sequence::iterator iterator; + typedef typename Sequence::value_type value_type; + + Sequence sc; + sc.push_back(0); + sc.push_back(1); + sc.push_back(2); + sc.push_back(3); + sc.push_back(4); + sc.push_back(5); + + iterator it; + + it=sc.begin(); + std::advance(it,3); + sc.relocate(sc.begin(),it); + CHECK_EQUAL(sc,(3)(0)(1)(2)(4)(5)); + BOOST_TEST(it==sc.begin()); + + sc.relocate(it,it); + CHECK_EQUAL(sc,(3)(0)(1)(2)(4)(5)); + + std::advance(it,3); + sc.relocate(sc.end(),it,sc.end()); + CHECK_EQUAL(sc,(3)(0)(1)(2)(4)(5)); + + sc.relocate(sc.begin(),it,it); + CHECK_EQUAL(sc,(3)(0)(1)(2)(4)(5)); + + iterator it2; + + it2=sc.begin(); + ++it2; + sc.relocate(it2,it,sc.end()); + CHECK_EQUAL(sc,(3)(2)(4)(5)(0)(1)); + BOOST_TEST(std::distance(it,it2)==3); + + sc.relocate(boost::prior(sc.end()),it,it2); + CHECK_EQUAL(sc,(3)(0)(2)(4)(5)(1)); + + std::vector<boost::reference_wrapper<const value_type> > v; + for(iterator it3=sc.begin();it3!=sc.end();++it3){ + v.push_back(boost::cref(*it3)); + } + + sc.rearrange(v.begin()); + BOOST_TEST(std::equal(sc.begin(),sc.end(),v.begin())); + + std::reverse(v.begin(),v.end()); + sc.rearrange(v.begin()); + BOOST_TEST(std::equal(sc.begin(),sc.end(),v.begin())); + + std::sort(v.begin(),v.end()); + sc.rearrange(v.begin()); + BOOST_TEST(std::equal(sc.begin(),sc.end(),v.begin())); + + std::reverse(v.begin(),v.begin()+v.size()/2); + sc.rearrange(v.begin()); + BOOST_TEST(std::equal(sc.begin(),sc.end(),v.begin())); +} + +#if BOOST_WORKAROUND(__MWERKS__,<=0x3003) +#pragma parse_func_templ reset +#endif + +void test_rearrange() +{ + typedef multi_index_container< + int, + indexed_by<sequenced<> > + > int_list; + + local_test_rearrange<int_list>(); + + typedef multi_index_container< + int, + indexed_by<random_access<> > + > int_vector; + + local_test_rearrange<int_vector>(); +} diff --git a/src/boost/libs/multi_index/test/test_rearrange.hpp b/src/boost/libs/multi_index/test/test_rearrange.hpp new file mode 100644 index 000000000..f3ec8457c --- /dev/null +++ b/src/boost/libs/multi_index/test/test_rearrange.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for rearrange operations. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_rearrange(); diff --git a/src/boost/libs/multi_index/test/test_rearrange_main.cpp b/src/boost/libs/multi_index/test/test_rearrange_main.cpp new file mode 100644 index 000000000..9fe5a65be --- /dev/null +++ b/src/boost/libs/multi_index/test/test_rearrange_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for rearrange operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_rearrange.hpp" + +int main() +{ + test_rearrange(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_safe_mode.cpp b/src/boost/libs/multi_index/test/test_safe_mode.cpp new file mode 100644 index 000000000..b5a7e796d --- /dev/null +++ b/src/boost/libs/multi_index/test/test_safe_mode.cpp @@ -0,0 +1,472 @@ +/* Boost.MultiIndex test for safe_mode. + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +#include "test_safe_mode.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include "pair_of_ints.hpp" +#include <stdexcept> +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +#define TRY_SAFE_MODE \ +try{ + +#define CATCH_SAFE_MODE(err) \ + throw std::runtime_error("safe mode violation not detected");\ +}catch(const safe_mode_exception& e){\ + if(e.error_code!=(err))throw std::runtime_error(\ + "safe mode violation not expected");\ +} + +template<typename T> void prevent_unused_var_warning(const T&){} + +template<typename Policy> +static void local_test_safe_mode( + std::forward_iterator_tag + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy)) +{ + typedef typename Policy::container container; + typedef typename Policy::index_type index_type; + typedef typename index_type::value_type value_type; + typedef typename index_type::iterator iterator; + + container c,c2; + index_type& i=Policy::index_from_container(c); + index_type& i2=Policy::index_from_container(c2); + Policy::insert(i,Policy::some_value()); + + TRY_SAFE_MODE + iterator it; + iterator it2=i.begin(); + it2=it; + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + iterator it; + value_type e=*it; + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + iterator it=i.end(); + value_type e=*it; + CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator) + + TRY_SAFE_MODE + iterator it=i.end(); + ++it; + CATCH_SAFE_MODE(safe_mode::not_incrementable_iterator) + + TRY_SAFE_MODE + iterator it; + iterator it2; + bool b=(it==it2); + prevent_unused_var_warning(b); + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + iterator it=i.begin(); + iterator it2; + bool b=(it==it2); + prevent_unused_var_warning(b); + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + iterator it=i.begin(); + iterator it2=i2.begin(); + bool b=(it==it2); + prevent_unused_var_warning(b); + CATCH_SAFE_MODE(safe_mode::not_same_owner) + + TRY_SAFE_MODE + i.erase(i.end(),i.begin()); + CATCH_SAFE_MODE(safe_mode::invalid_range) + + TRY_SAFE_MODE + iterator it; + Policy::insert(i,it,Policy::some_value()); + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + i.erase(i.end()); + CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator) + + TRY_SAFE_MODE + iterator it=i.begin(); + Policy::insert(i2,it,Policy::some_value()); + CATCH_SAFE_MODE(safe_mode::not_owner) + + TRY_SAFE_MODE + iterator it=i.begin(); + iterator it2=i2.end(); + i2.erase(it,it2); + CATCH_SAFE_MODE(safe_mode::not_owner) + + TRY_SAFE_MODE + iterator it=Policy::insert(i,Policy::another_value()); + i.erase(it); + i.erase(it); + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + container c3(c); + index_type& i3=Policy::index_from_container(c3); + iterator it=Policy::insert(i3,Policy::another_value()); + i3.clear(); + i3.erase(it); + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + iterator it; + { + container c3; + index_type& i3=Policy::index_from_container(c3); + it=i3.end(); + } + iterator it2; + it2=it; + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + iterator it; + { + container c3; + index_type& i3=Policy::index_from_container(c3); + it=Policy::insert(i3,Policy::some_value()); + } + value_type e=*it; + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + iterator it; + { + container c3; + index_type& i3=Policy::index_from_container(c3); + it=Policy::insert(i3,Policy::some_value()); + } + iterator it2; + it2=it; + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + container c3(c); + container c4; + index_type& i3=Policy::index_from_container(c3); + index_type& i4=Policy::index_from_container(c4); + iterator it=i3.begin(); + i3.swap(i4); + i3.erase(it); + CATCH_SAFE_MODE(safe_mode::not_owner) + + /* this, unlike the previous case, is indeed correct, test safe mode + * gets it right + */ + { + container c3(c); + container c4; + index_type& i3=Policy::index_from_container(c3); + index_type& i4=Policy::index_from_container(c4); + iterator it=i3.begin(); + i3.swap(i4); + i4.erase(it); + } + + TRY_SAFE_MODE + iterator it=i.end(); + typename container::iterator it2=project<0>(c2,it); + CATCH_SAFE_MODE(safe_mode::not_owner) + + TRY_SAFE_MODE + iterator it=Policy::insert(i,Policy::another_value()); + typename container::iterator it2=project<0>(c,it); + i.erase(it); + value_type e=*it2; + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + /* testcase for bug reported at + * http://lists.boost.org/boost-users/2006/02/17230.php + */ + { + container c3(c); + index_type& i3=Policy::index_from_container(c3); + iterator it=i3.end(); + i3.clear(); + it=i3.end(); + } + + /* testcase for doppelganger bug of that discovered for STLport at + * http://lists.boost.org/Archives/boost/2006/04/102740.php + */ + { + container c3; + index_type& i3=Policy::index_from_container(c3); + iterator it=i3.end(); + i3.clear(); + iterator it2=it; + BOOST_TEST(it2==i3.end()); + } +} + +template<typename Policy> +static void local_test_safe_mode( + std::bidirectional_iterator_tag + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy)) +{ + ::local_test_safe_mode<Policy>(std::forward_iterator_tag()); + + typedef typename Policy::container container; + typedef typename Policy::index_type index_type; + typedef typename index_type::iterator iterator; + + container c; + index_type& i=Policy::index_from_container(c); + Policy::insert(i,Policy::some_value()); + + TRY_SAFE_MODE + iterator it=i.begin(); + --it; + CATCH_SAFE_MODE(safe_mode::not_decrementable_iterator) +} + +template<typename Policy> +static void local_test_safe_mode( + std::random_access_iterator_tag + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy)) +{ + ::local_test_safe_mode<Policy>(std::bidirectional_iterator_tag()); + + typedef typename Policy::container container; + typedef typename Policy::index_type index_type; + typedef typename index_type::iterator iterator; + + container c; + index_type& i=Policy::index_from_container(c); + Policy::insert(i,Policy::some_value()); + + TRY_SAFE_MODE + iterator it=i.begin(); + it+=2; + CATCH_SAFE_MODE(safe_mode::out_of_bounds) + + TRY_SAFE_MODE + iterator it=i.begin(); + it-=1; + CATCH_SAFE_MODE(safe_mode::out_of_bounds) +} + +template<typename Policy> +static void local_test_safe_mode() +{ + typedef typename Policy::index_type::iterator::iterator_category category; + ::local_test_safe_mode<Policy>(category()); +} + +template<typename Policy> +static void local_test_safe_mode_with_rearrange() +{ + ::local_test_safe_mode<Policy>(); + + typedef typename Policy::container container; + typedef typename Policy::index_type index_type; + typedef typename index_type::iterator iterator; + + container c; + index_type& i=Policy::index_from_container(c); + Policy::insert(i,Policy::some_value()); + + TRY_SAFE_MODE + iterator it; + i.splice(it,i,i.begin(),i.end()); + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + container c2(c); + index_type& i2=Policy::index_from_container(c2); + iterator it2=i2.begin(); + iterator it=i.begin(); + i.splice(it2,i2,it); + CATCH_SAFE_MODE(safe_mode::not_owner) + + TRY_SAFE_MODE + i.splice(i.begin(),i,i.begin(),i.end()); + CATCH_SAFE_MODE(safe_mode::inside_range) + + TRY_SAFE_MODE + i.splice(i.begin(),i,i.end(),i.begin()); + CATCH_SAFE_MODE(safe_mode::invalid_range) + + TRY_SAFE_MODE + i.splice(i.begin(),i); + CATCH_SAFE_MODE(safe_mode::same_container) + + TRY_SAFE_MODE + iterator it; + i.relocate(it,i.begin(),i.end()); + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + i.relocate(i.begin(),i.begin(),i.end()); + CATCH_SAFE_MODE(safe_mode::inside_range) + + TRY_SAFE_MODE + i.relocate(i.begin(),i.end(),i.begin()); + CATCH_SAFE_MODE(safe_mode::invalid_range) +} + +template<typename MultiIndexContainer,int N> +struct index_policy_base +{ + typedef MultiIndexContainer container; + typedef typename nth_index<container,N>::type index_type; + + static index_type& index_from_container(container& c){return get<N>(c);} +}; + +template<typename MultiIndexContainer,int N> +struct key_based_index_policy_base: + index_policy_base<MultiIndexContainer,N> +{ + typedef index_policy_base<MultiIndexContainer,N> super; + + typedef typename super::container container; + typedef typename super::index_type index_type; + typedef typename index_type::value_type value_type; + typedef typename index_type::iterator iterator; + + static iterator insert(index_type& i,const value_type& v) + { + return i.insert(v).first; + } + + static iterator insert(index_type& i,iterator it,const value_type& v) + { + return i.insert(it,v); + } +}; + +template<typename MultiIndexContainer,int N> +struct non_key_based_index_policy_base: + index_policy_base<MultiIndexContainer,N> +{ + typedef index_policy_base<MultiIndexContainer,N> super; + + typedef typename super::container container; + typedef typename super::index_type index_type; + typedef typename index_type::value_type value_type; + typedef typename index_type::iterator iterator; + + static iterator insert(index_type& i,const value_type& v) + { + return i.push_back(v).first; + } + + static iterator insert(index_type& i,iterator it,const value_type& v) + { + return i.insert(it,v).first; + } +}; + +struct employee_set_policy_base +{ + static employee some_value(){return employee(0,"Joe",31,1123);} + static employee another_value(){return employee(1,"Robert",27,5601);} +}; + +struct employee_set_policy: + employee_set_policy_base, + key_based_index_policy_base<employee_set,0> +{}; + +struct employee_set_by_name_policy: + employee_set_policy_base, + key_based_index_policy_base<employee_set,1> +{}; + +struct employee_set_as_inserted_policy: + employee_set_policy_base, + non_key_based_index_policy_base<employee_set,3> +{}; + +struct employee_set_randomly_policy: + employee_set_policy_base, + non_key_based_index_policy_base<employee_set,5> +{}; + +template<typename IntegralBimap> +static void test_integral_bimap() +{ + typedef typename IntegralBimap::value_type value_type; + typedef typename IntegralBimap::iterator iterator; + + TRY_SAFE_MODE + IntegralBimap bm; + iterator it=bm.insert(value_type(0,0)).first; + bm.insert(value_type(1,1)); + bm.modify(it,increment_first); + value_type v=*it; + prevent_unused_var_warning(v); + CATCH_SAFE_MODE(safe_mode::invalid_iterator) + + TRY_SAFE_MODE + IntegralBimap bm; + iterator it=bm.insert(value_type(0,0)).first; + bm.insert(value_type(1,1)); + bm.modify(it,increment_second); + pair_of_ints v=*it; + prevent_unused_var_warning(v); + CATCH_SAFE_MODE(safe_mode::invalid_iterator) +} + +void test_safe_mode() +{ + local_test_safe_mode<employee_set_policy>(); + local_test_safe_mode<employee_set_by_name_policy>(); + local_test_safe_mode_with_rearrange<employee_set_as_inserted_policy>(); + local_test_safe_mode_with_rearrange<employee_set_randomly_policy>(); + + typedef multi_index_container< + pair_of_ints, + indexed_by< + ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>, + ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> > + > bimap0_type; + + test_integral_bimap<bimap0_type>(); + + typedef multi_index_container< + pair_of_ints, + indexed_by< + ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>, + hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> > + > bimap1_type; + + test_integral_bimap<bimap1_type>(); + + typedef multi_index_container< + pair_of_ints, + indexed_by< + hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>, + ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> > + > bimap2_type; + + test_integral_bimap<bimap2_type>(); + + typedef multi_index_container< + pair_of_ints, + indexed_by< + hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>, + hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> > + > bimap3_type; + + test_integral_bimap<bimap3_type>(); +} diff --git a/src/boost/libs/multi_index/test/test_safe_mode.hpp b/src/boost/libs/multi_index/test/test_safe_mode.hpp new file mode 100644 index 000000000..156d7b275 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_safe_mode.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for safe mode. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_safe_mode(); diff --git a/src/boost/libs/multi_index/test/test_safe_mode_main.cpp b/src/boost/libs/multi_index/test/test_safe_mode_main.cpp new file mode 100644 index 000000000..4bb892c6c --- /dev/null +++ b/src/boost/libs/multi_index/test/test_safe_mode_main.cpp @@ -0,0 +1,19 @@ +/* Boost.MultiIndex test for safe mode. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_safe_mode.hpp" + +int main() +{ + test_safe_mode(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/multi_index/test/test_serialization.cpp b/src/boost/libs/multi_index/test/test_serialization.cpp new file mode 100644 index 000000000..6c5b8f6e7 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization.cpp @@ -0,0 +1,21 @@ +/* Boost.MultiIndex test for serialization. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#include "test_serialization.hpp" +#include "test_serialization1.hpp" +#include "test_serialization2.hpp" +#include "test_serialization3.hpp" + +void test_serialization() +{ + test_serialization1(); + test_serialization2(); + test_serialization3(); +} diff --git a/src/boost/libs/multi_index/test/test_serialization.hpp b/src/boost/libs/multi_index/test/test_serialization.hpp new file mode 100644 index 000000000..8e66535fe --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for serialization. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_serialization(); diff --git a/src/boost/libs/multi_index/test/test_serialization1.cpp b/src/boost/libs/multi_index/test/test_serialization1.cpp new file mode 100644 index 000000000..f41c9ca5a --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization1.cpp @@ -0,0 +1,66 @@ +/* Boost.MultiIndex test for serialization, part 1. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#include "test_serialization1.hpp" +#include "test_serialization_template.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/multi_index/random_access_index.hpp> +#include <boost/multi_index/key_extractors.hpp> +#include "non_std_allocator.hpp" + +using namespace boost::multi_index; + +void test_serialization1() +{ + { + typedef multi_index_container< + int, + indexed_by< + sequenced<>, + sequenced<>, + random_access<> + > + > multi_index_t; + + multi_index_t m; + for(int i=0;i<100;++i)m.push_back(i); + m.reverse(); + test_serialization(m); + + m.clear(); + for(int j=50;j<100;++j)m.push_back(j); + for(int k=0;k<50;++k)m.push_back(k); + m.sort(); + test_serialization(m); + } + { + typedef multi_index_container< + int, + indexed_by< + random_access<>, + sequenced<>, + ordered_non_unique<identity<int> > + >, + non_std_allocator<int> + > multi_index_t; + + multi_index_t m; + for(int i=0;i<100;++i){ + m.push_back(i); + m.push_back(i); + m.push_back(i); + } + m.reverse(); + test_serialization(m); + } +} diff --git a/src/boost/libs/multi_index/test/test_serialization1.hpp b/src/boost/libs/multi_index/test/test_serialization1.hpp new file mode 100644 index 000000000..2db6ec8d3 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization1.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for serialization, part 1. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_serialization1(); diff --git a/src/boost/libs/multi_index/test/test_serialization2.cpp b/src/boost/libs/multi_index/test/test_serialization2.cpp new file mode 100644 index 000000000..1c93c5fa6 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization2.cpp @@ -0,0 +1,81 @@ +/* Boost.MultiIndex test for serialization, part 2. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +#include "test_serialization2.hpp" +#include "test_serialization_template.hpp" + +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/multi_index/random_access_index.hpp> +#include <boost/multi_index/key_extractors.hpp> +#include "non_std_allocator.hpp" +#include "pair_of_ints.hpp" + +using namespace boost::multi_index; + +void test_serialization2() +{ + { + typedef multi_index_container< + pair_of_ints, + indexed_by< + ordered_unique< + BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first) + >, + ordered_non_unique< + BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second) + >, + random_access<>, + sequenced<> + >, + non_std_allocator<pair_of_ints> + > multi_index_t; + + multi_index_t m; + test_serialization(m); + + m.insert(pair_of_ints(4,0)); + test_serialization(m); + + m.insert(pair_of_ints(3,1)); + m.insert(pair_of_ints(2,1)); + test_serialization(m); + + m.insert(pair_of_ints(1,1)); + test_serialization(m); + + m.insert(pair_of_ints(0,0)); + test_serialization(m); + + m.insert(pair_of_ints(5,1)); + m.insert(pair_of_ints(7,1)); + m.insert(pair_of_ints(6,1)); + test_serialization(m); + + m.insert(pair_of_ints(8,1)); + m.insert(pair_of_ints(9,1)); + m.insert(pair_of_ints(12,1)); + m.insert(pair_of_ints(11,1)); + m.insert(pair_of_ints(10,1)); + test_serialization(m); + + /* testcase for bug reported at + * http://lists.boost.org/boost-users/2006/05/19362.php + */ + + m.clear(); + m.insert(pair_of_ints(0,0)); + m.insert(pair_of_ints(1,0)); + m.insert(pair_of_ints(2,1)); + m.insert(pair_of_ints(4,2)); + m.insert(pair_of_ints(3,2)); + test_serialization(m); + } +} diff --git a/src/boost/libs/multi_index/test/test_serialization2.hpp b/src/boost/libs/multi_index/test/test_serialization2.hpp new file mode 100644 index 000000000..6382882f6 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization2.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for serialization, part 2. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_serialization2(); diff --git a/src/boost/libs/multi_index/test/test_serialization3.cpp b/src/boost/libs/multi_index/test/test_serialization3.cpp new file mode 100644 index 000000000..5a759c1d5 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization3.cpp @@ -0,0 +1,216 @@ +/* Boost.MultiIndex test for serialization, part 3. + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +#include "test_serialization3.hpp" +#include "test_serialization_template.hpp" + +#include <boost/move/core.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/multi_index/ordered_index.hpp> +#include <boost/multi_index/key_extractors.hpp> +#include "non_std_allocator.hpp" + +struct non_default_ctble +{ + non_default_ctble(int n_):n(n_){} + + bool operator==(const non_default_ctble& x)const{return n==x.n;} + + int n; +}; + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +namespace boost{ +namespace serialization{ +#endif + +template<class Archive> +void save_construct_data( + Archive& ar,const non_default_ctble* p,const unsigned int version) +{ + if(version<3)return; + + ar<<boost::serialization::make_nvp("n",p->n); +} + +template<class Archive> +void load_construct_data( + Archive& ar,non_default_ctble* p,const unsigned int version) +{ + if(version<3)return; + + int n=0; + ar>>boost::serialization::make_nvp("n",n); + ::new(p)non_default_ctble(n); +} + +template<class Archive> +void serialize(Archive&,non_default_ctble&,const unsigned int) +{ +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +} /* namespace serialization */ +} /* namespace boost*/ +#endif + +namespace boost{ +namespace serialization{ +template<> struct version<non_default_ctble> +{ + BOOST_STATIC_CONSTANT(int,value=3); +}; +} /* namespace serialization */ +} /* namespace boost*/ + +struct non_copyable +{ + non_copyable(int n_=0):n(n_){} + non_copyable(BOOST_RV_REF(non_copyable) x):n(x.n){} + + bool operator==(const non_copyable& x)const{return n==x.n;} + bool operator<(const non_copyable& x)const{return n<x.n;} + + int n; + +private: + BOOST_MOVABLE_BUT_NOT_COPYABLE(non_copyable) +}; + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +namespace boost{ +namespace serialization{ +#endif + +template<class Archive> +void serialize(Archive& ar,non_copyable& x,const unsigned int) +{ + ar&boost::serialization::make_nvp("n",x.n); +} + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +} /* namespace serialization */ +} /* namespace boost*/ +#endif + +using namespace boost::multi_index; + +void test_serialization3() +{ + const int N=100; + const int SHUFFLE=10232; + + typedef multi_index_container< + int, + indexed_by< + hashed_unique<identity<int> >, + sequenced<> + >, + non_std_allocator<int> + > hashed_set; + + typedef hashed_set::iterator iterator; + typedef hashed_set::local_iterator local_iterator; + + hashed_set hs; + + for(int i=0;i<N;++i){ + hs.insert(i*SHUFFLE); + } + + std::ostringstream oss; + { + boost::archive::text_oarchive oa(oss); + oa<<const_cast<const hashed_set&>(hs); + + std::vector<iterator> its(N); + for(int i=0;i<N;++i){ + iterator it=hs.find(i*SHUFFLE); + its.push_back(it); + oa<<const_cast<const iterator&>(its.back()); + } + iterator it=hs.end(); + oa<<const_cast<const iterator&>(it); + + std::vector<local_iterator> lits(2*N); + for(std::size_t buc=0;buc<hs.bucket_count();++buc){ + for(local_iterator lit=hs.begin(buc),lit_end=hs.end(buc); + lit!=lit_end;++lit){ + oa<<*lit; + lits.push_back(lit); + oa<<const_cast<const local_iterator&>(lits.back()); + } + local_iterator lit2=hs.end(buc); + lits.push_back(lit2); + oa<<const_cast<const local_iterator&>(lits.back()); + } + } + + hashed_set hs2; + std::istringstream iss(oss.str()); + boost::archive::text_iarchive ia(iss); + ia>>hs2; + BOOST_TEST(boost::multi_index::get<1>(hs)==boost::multi_index::get<1>(hs2)); + + for(int j=0;j<N;++j){ + iterator it; + ia>>it; + BOOST_TEST(*it==j*SHUFFLE); + } + iterator it; + ia>>it; + BOOST_TEST(it==hs2.end()); + + for(std::size_t buc=0;buc<hs2.bucket_count();++buc){ + for(std::size_t k=0;k<hs2.bucket_size(buc);++k){ + int n; + local_iterator it_; + ia>>n; + ia>>it_; + BOOST_TEST(*it_==n); + } + local_iterator it2; + ia>>it2; + BOOST_TEST(it2==hs2.end(buc)); + } + + { + typedef multi_index_container< + non_default_ctble, + indexed_by< + ordered_unique< + BOOST_MULTI_INDEX_MEMBER(non_default_ctble,int,n) + > + > + > multi_index_t; + + multi_index_t m; + for(int i=0;i<100;++i)m.insert(non_default_ctble(i)); + test_serialization(m); + } + + { + /* testcase for https://svn.boost.org/trac10/ticket/13478 */ + + typedef multi_index_container< + non_copyable, + indexed_by< + ordered_unique< + BOOST_MULTI_INDEX_MEMBER(non_copyable,int,n) + > + > + > multi_index_t; + + multi_index_t m; + for(int i=0;i<100;++i)m.emplace(i); + test_serialization(m); + } +} diff --git a/src/boost/libs/multi_index/test/test_serialization3.hpp b/src/boost/libs/multi_index/test/test_serialization3.hpp new file mode 100644 index 000000000..bb620c0b6 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization3.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for serialization, part 3. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_serialization3(); diff --git a/src/boost/libs/multi_index/test/test_serialization_main.cpp b/src/boost/libs/multi_index/test/test_serialization_main.cpp new file mode 100644 index 000000000..43a698a77 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for serialization. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_serialization.hpp" + +int main() +{ + test_serialization(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_serialization_template.hpp b/src/boost/libs/multi_index/test/test_serialization_template.hpp new file mode 100644 index 000000000..b7a9a9c92 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_serialization_template.hpp @@ -0,0 +1,105 @@ +/* Boost.MultiIndex serialization tests template. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <boost/archive/text_oarchive.hpp> +#include <boost/archive/text_iarchive.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/mpl/size.hpp> +#include "pre_multi_index.hpp" +#include <boost/multi_index_container.hpp> +#include <string> +#include <sstream> +#include <vector> + +template<int N> +struct all_indices_equal_helper +{ + template<class MultiIndexContainer> + static bool compare( + const MultiIndexContainer& m1,const MultiIndexContainer& m2) + { + if(!(boost::multi_index::get<N>(m1)==boost::multi_index::get<N>(m2))){ + return false; + } + return all_indices_equal_helper<N-1>::compare(m1,m2); + } +}; + +template<> +struct all_indices_equal_helper<0> +{ + template<class MultiIndexContainer> + static bool compare( + const MultiIndexContainer&,const MultiIndexContainer&) + { + return true; + } +}; + +template<class MultiIndexContainer> +bool all_indices_equal( + const MultiIndexContainer& m1,const MultiIndexContainer& m2) +{ + BOOST_STATIC_CONSTANT(int, + N=boost::mpl::size< + BOOST_DEDUCED_TYPENAME MultiIndexContainer::index_type_list>::type::value); + + return all_indices_equal_helper<N-1>::compare(m1,m2); +} + +template<class MultiIndexContainer> +void test_serialization(const MultiIndexContainer& m) +{ + typedef typename MultiIndexContainer::iterator iterator; + typedef typename MultiIndexContainer::const_iterator const_iterator; + + std::ostringstream oss; + { + boost::archive::text_oarchive oa(oss); + oa<<m; + + std::vector<const_iterator> its(m.size()); + const_iterator it_end=m.end(); + for(const_iterator it=m.begin();it!=it_end;++it){ + its.push_back(it); + oa<<const_cast<const const_iterator&>(its.back()); + } + oa<<const_cast<const const_iterator&>(it_end); + } + + MultiIndexContainer m2; + std::istringstream iss(oss.str()); + boost::archive::text_iarchive ia(iss); + ia>>m2; + BOOST_TEST(all_indices_equal(m,m2)); + + iterator it_end=m2.end(); + for(iterator it=m2.begin();it!=it_end;++it){ + iterator it2; + ia>>it2; + BOOST_TEST(it==it2); + + /* exercise safe mode with this (unchecked) iterator */ + BOOST_TEST(*it==*it2); + m2.erase(it,it2); + m2.erase(it2,it2); + m2.erase(it2,it); + iterator it3(++it2); + iterator it4; + it4=--it2; + BOOST_TEST(it==it4); + BOOST_TEST(it==boost::multi_index::project<0>(m2,it4)); + } + iterator it2; + ia>>it2; + BOOST_TEST(it_end==it2); + BOOST_TEST(it_end==boost::multi_index::project<0>(m2,it2)); +} diff --git a/src/boost/libs/multi_index/test/test_set_ops.cpp b/src/boost/libs/multi_index/test/test_set_ops.cpp new file mode 100644 index 000000000..0e9a70da8 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_set_ops.cpp @@ -0,0 +1,127 @@ +/* Boost.MultiIndex test for standard set operations. + * + * Copyright 2003-2014 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/multi_index for library home page. + */ + +#include "test_set_ops.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <vector> +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +struct type1{}; + +struct type2 +{ +private: + operator type1()const{return type1();} +}; + +struct type3 +{ + operator type1()const{return type1();} +}; + +struct less_type12 +{ + bool operator()(type1,type1)const{return false;} + bool operator()(type1,type2)const{return false;} + bool operator()(type2,type1)const{return false;} +}; + +bool less_type1_f(type1,type1){return false;} + +struct hash_type12 +{ + std::size_t operator()(type1)const{return 0;} + std::size_t operator()(type2)const{return 0;} +}; + +struct eq_type12 +{ + bool operator()(type1,type1)const{return true;} + bool operator()(type1,type2)const{return true;} + bool operator()(type2,type1)const{return true;} +}; + +void test_set_ops() +{ + employee_set es; + employee_set_by_name& i1=get<by_name>(es); + const employee_set_by_age& i2=get<age>(es); + employee_set_by_ssn& i4=get<ssn>(es); + + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + es.insert(employee(3,"Albert",20,9012)); + es.insert(employee(4,"John",57,1002)); + + BOOST_TEST(i1.find("John")->name=="John"); + BOOST_TEST(i2.find(41)==i2.end()); + BOOST_TEST(i4.find(5601)->name=="Robert"); + + BOOST_TEST(i1.count("John")==2); + BOOST_TEST(es.count(employee(10,"",-1,0))==0); + BOOST_TEST(i4.count(7881)==0); + + BOOST_TEST( + std::distance( + i2.lower_bound(31), + i2.upper_bound(60))==3); + + std::pair<employee_set_by_name::iterator,employee_set_by_name::iterator> p= + i1.equal_range("John"); + BOOST_TEST(std::distance(p.first,p.second)==2); + + p=i1.equal_range("Serena"); + BOOST_TEST(p.first==i1.end()&&p.second==i1.end()); + + std::pair<employee_set_by_age::iterator,employee_set_by_age::iterator> p2= + i2.equal_range(30); + BOOST_TEST(p2.first==p2.second&&p2.first->age==31); + + /* check promotion detection plays nice with private conversion */ + + multi_index_container< + type1, + indexed_by< + ordered_unique<identity<type1>,less_type12>, + hashed_unique<identity<type1>,hash_type12,eq_type12> + > + > c; + c.insert(type1()); + + BOOST_TEST(c.find(type2())==c.begin()); + BOOST_TEST(c.count(type2())==1); + BOOST_TEST(c.lower_bound(type2())==c.begin()); + BOOST_TEST(c.upper_bound(type2())==c.end()); + BOOST_TEST(c.equal_range(type2())==std::make_pair(c.begin(),c.end())); + + BOOST_TEST(c.get<1>().find(type2())==c.get<1>().begin()); + BOOST_TEST(c.get<1>().count(type2())==1); + BOOST_TEST(c.get<1>().equal_range(type2())== + std::make_pair(c.get<1>().begin(),c.get<1>().end())); + + /* check promotion detection does not break with functions */ + + multi_index_container< + type1, + indexed_by< + ordered_unique<identity<type1>,bool(*)(type1,type1)> + > + > c2(boost::make_tuple(boost::make_tuple(identity<type1>(),&less_type1_f))); + c2.insert(type1()); + + BOOST_TEST(c2.find(type3())==c2.begin()); +} diff --git a/src/boost/libs/multi_index/test/test_set_ops.hpp b/src/boost/libs/multi_index/test/test_set_ops.hpp new file mode 100644 index 000000000..dc333c887 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_set_ops.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for standard set operations. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_set_ops(); diff --git a/src/boost/libs/multi_index/test/test_set_ops_main.cpp b/src/boost/libs/multi_index/test/test_set_ops_main.cpp new file mode 100644 index 000000000..9a45a73e2 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_set_ops_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for standard set operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_set_ops.hpp" + +int main() +{ + test_set_ops(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_special_set_ops.cpp b/src/boost/libs/multi_index/test/test_special_set_ops.cpp new file mode 100644 index 000000000..516a2cc6a --- /dev/null +++ b/src/boost/libs/multi_index/test/test_special_set_ops.cpp @@ -0,0 +1,95 @@ +/* Boost.MultiIndex test for special set operations. + * + * Copyright 2003-2015 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/multi_index for library home page. + */ + +#include "test_special_set_ops.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <sstream> +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include <boost/detail/lightweight_test.hpp> + +using namespace boost::multi_index; + +static int string_to_int(const std::string& str) +{ + std::istringstream iss(str); + int res; + iss>>res; + return res; +} + +struct comp_int_string +{ + bool operator()(int x,const std::string& y)const + { + return x<string_to_int(y); + } + + bool operator()(const std::string& x,int y)const + { + return string_to_int(x)<y; + } +}; + +struct hash_string_as_int +{ + int operator()(const std::string& x)const + { + return static_cast<int>(boost::hash<int>()(string_to_int(x))); + } +}; + +struct eq_string_int +{ + bool operator()(int x,const std::string& y)const + { + return x==string_to_int(y); + } + + bool operator()(const std::string& x,int y)const + { + return operator()(y,x); + } +}; + +void test_special_set_ops() +{ + employee_set es; + + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + es.insert(employee(3,"Albert",20,9012)); + es.insert(employee(4,"John",57,1002)); + + std::pair<employee_set_by_ssn::iterator,employee_set_by_ssn::iterator> p= + get<ssn>(es).equal_range( + "7889",hash_string_as_int(),eq_string_int()); + + BOOST_TEST(std::distance(p.first,p.second)==1&&(p.first)->id==2); + + BOOST_TEST( + get<ssn>(es).count( + "5601",hash_string_as_int(),eq_string_int())==1); + + BOOST_TEST( + get<ssn>(es).find( + "1123",hash_string_as_int(),eq_string_int())->name=="Joe"); + + BOOST_TEST( + std::distance( + get<age>(es).lower_bound("27",comp_int_string()), + get<age>(es).upper_bound("40",comp_int_string()))==3); + + BOOST_TEST(es.count(2,employee::comp_id())==1); + BOOST_TEST(es.count(5,employee::comp_id())==0); +} diff --git a/src/boost/libs/multi_index/test/test_special_set_ops.hpp b/src/boost/libs/multi_index/test/test_special_set_ops.hpp new file mode 100644 index 000000000..a9434de58 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_special_set_ops.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for special set operations. + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_special_set_ops(); diff --git a/src/boost/libs/multi_index/test/test_special_set_ops_main.cpp b/src/boost/libs/multi_index/test/test_special_set_ops_main.cpp new file mode 100644 index 000000000..843f86d0c --- /dev/null +++ b/src/boost/libs/multi_index/test/test_special_set_ops_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for special set operations. + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_special_set_ops.hpp" + +int main() +{ + test_special_set_ops(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test/test_update.cpp b/src/boost/libs/multi_index/test/test_update.cpp new file mode 100644 index 000000000..56e9c827f --- /dev/null +++ b/src/boost/libs/multi_index/test/test_update.cpp @@ -0,0 +1,281 @@ +/* Boost.MultiIndex test for replace(), modify() and modify_key(). + * + * Copyright 2003-2018 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/multi_index for library home page. + */ + +#include "test_update.hpp" + +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ +#include <algorithm> +#include <cstddef> +#include "pre_multi_index.hpp" +#include "employee.hpp" +#include "pair_of_ints.hpp" +#include <boost/detail/lightweight_test.hpp> +#include <boost/next_prior.hpp> + +struct do_nothing +{ + template<typename T> + void operator()(const T&)const{} +}; + +struct null_hash +{ + template<typename T> + std::size_t operator()(const T&)const{return 0;} +}; + +struct assign_value +{ + assign_value(int n):n_(n){} + + void operator()(int& x)const{x=n_;} + + int n_; +}; + +template<class MultiIndexContainer> +void test_stable_update() +{ + typedef typename MultiIndexContainer::iterator iterator; + typedef typename MultiIndexContainer::size_type size_type; + typedef typename MultiIndexContainer::difference_type difference_type; + + MultiIndexContainer c; + c.insert(0); + c.insert(1);c.insert(1); + c.insert(2);c.insert(2);c.insert(2);c.insert(2); + c.insert(3); + c.insert(4);c.insert(4);c.insert(4); + c.insert(5);c.insert(5); + c.insert(6); + c.insert(7); + size_type num_elems= + c.count(0)+c.count(1)+c.count(2)+c.count(3)+ + c.count(4)+c.count(5)+c.count(6)+c.count(7); + + for(size_type n=c.size();n--;){ + iterator it=boost::next(c.begin(),(difference_type)n); + + c.replace(it,*it); + BOOST_TEST((size_type)std::distance(c.begin(),it)==n); + + c.modify(it,do_nothing()); + BOOST_TEST((size_type)std::distance(c.begin(),it)==n); + + c.modify(it,do_nothing(),do_nothing()); + BOOST_TEST((size_type)std::distance(c.begin(),it)==n); + + for(int i=0;i<=8;++i){ + MultiIndexContainer cpy(c); + bool b=c.modify(it,assign_value(i),assign_value(*it)); + BOOST_TEST(b||(size_type)std::distance(c.begin(),it)==n); + BOOST_TEST(c.count(0)+c.count(1)+c.count(2)+c.count(3)+c.count(4)+ + c.count(5)+c.count(6)+c.count(7)+c.count(8)==num_elems); + if(b){ + c=cpy; + it=boost::next(c.begin(),(difference_type)n); + } + } + } +} + +using namespace boost::multi_index; + +void test_update() +{ + employee_set es; + employee_set_as_inserted& i=get<as_inserted>(es); + employee_set_randomly& r=get<randomly>(es); + + es.insert(employee(0,"Joe",31,1123)); + es.insert(employee(1,"Robert",27,5601)); + es.insert(employee(2,"John",40,7889)); + es.insert(employee(3,"Olbert",20,9012)); + es.insert(employee(4,"John",57,1002)); + + employee_set::iterator it=es.find(employee(0,"Joe",31,1123)); + employee_set_as_inserted::iterator it1= + project<as_inserted>(es,get<name>(es).find("Olbert")); + employee_set_randomly::iterator it2= + project<randomly>(es,get<age>(es).find(57)); + + BOOST_TEST(es.replace(it,*it)); + BOOST_TEST(i.replace(it1,*it1)); + BOOST_TEST(r.replace(it2,*it2)); + BOOST_TEST(!es.replace(it,employee(3,"Joe",31,1123))&&it->id==0); + BOOST_TEST(es.replace(it,employee(0,"Joe",32,1123))&&it->age==32); + BOOST_TEST(i.replace(it1,employee(3,"Albert",20,9012))&&it1->name== + "Albert"); + BOOST_TEST(!r.replace(it2,employee(4,"John",57,5601))); + + { + typedef multi_index_container< + pair_of_ints, + indexed_by< + ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>, + hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)>, + sequenced<> > > + int_int_set; + + int_int_set iis; + nth_index<int_int_set,1>::type& ii1=get<1>(iis); + nth_index<int_int_set,2>::type& ii2=get<2>(iis); + iis.insert(pair_of_ints(0,0)); + iis.insert(pair_of_ints(5,5)); + iis.insert(pair_of_ints(10,10)); + + BOOST_TEST(!iis.replace(iis.begin(),pair_of_ints(5,0))); + BOOST_TEST(!ii2.replace(ii2.begin(),pair_of_ints(0,5))); + BOOST_TEST(!ii1.replace(project<1>(iis,iis.begin()),pair_of_ints(5,11))); + BOOST_TEST(!iis.replace(iis.begin(),pair_of_ints(11,5))); + BOOST_TEST(!iis.replace(boost::next(iis.begin()),pair_of_ints(10,5))); + BOOST_TEST(!ii1.replace( + project<1>(iis,boost::next(iis.begin())),pair_of_ints(5,10))); + BOOST_TEST(!iis.replace(boost::prior(iis.end()),pair_of_ints(5,10))); + BOOST_TEST(!ii2.replace(boost::prior(ii2.end()),pair_of_ints(10,5))); + + BOOST_TEST(iis.modify(iis.begin(),increment_first)); + BOOST_TEST(ii2.modify(ii2.begin(),increment_first)); + BOOST_TEST(ii1.modify(project<1>(iis,iis.begin()),increment_first)); + BOOST_TEST(ii2.modify(ii2.begin(),increment_first,decrement_first)); + + BOOST_TEST(!iis.modify(iis.begin(),increment_first,decrement_first)); + BOOST_TEST(iis.size()==3); + + BOOST_TEST(!iis.modify(iis.begin(),increment_first)); + BOOST_TEST(iis.size()==2); + + iis.insert(pair_of_ints(0,0)); + BOOST_TEST(ii2.modify(boost::prior(ii2.end()),increment_second)); + BOOST_TEST(iis.modify(iis.begin(),increment_second)); + BOOST_TEST(ii2.modify(boost::prior(ii2.end()),increment_second)); + BOOST_TEST(iis.modify(iis.begin(),increment_second,decrement_second)); + + BOOST_TEST(!ii2.modify( + boost::prior(ii2.end()),increment_second,decrement_second)); + BOOST_TEST(ii2.size()==3); + + BOOST_TEST(!ii2.modify(boost::prior(ii2.end()),increment_second)); + BOOST_TEST(ii2.size()==2); + + iis.insert(pair_of_ints(0,0)); + BOOST_TEST(iis.modify_key(iis.begin(),increment_int)); + BOOST_TEST(iis.modify_key(iis.begin(),increment_int,decrement_int)); + BOOST_TEST(iis.modify_key(iis.begin(),increment_int)); + BOOST_TEST(iis.modify_key(iis.begin(),increment_int)); + + BOOST_TEST(!iis.modify_key(iis.begin(),increment_int,decrement_int)); + BOOST_TEST(iis.size()==3); + + BOOST_TEST(!iis.modify_key(iis.begin(),increment_int)); + BOOST_TEST(iis.size()==2); + + nth_index_iterator<int_int_set,1>::type it_=ii1.find(5); + BOOST_TEST(ii1.modify_key(it_,increment_int)); + BOOST_TEST(ii1.modify_key(it_,increment_int)); + BOOST_TEST(ii1.modify_key(it_,increment_int,decrement_int)); + BOOST_TEST(ii1.modify_key(it_,increment_int)); + + BOOST_TEST(!ii1.modify_key(it_,increment_int,decrement_int)); + BOOST_TEST(ii1.size()==2); + + BOOST_TEST(!ii1.modify_key(it_,increment_int)); + BOOST_TEST(ii1.size()==1); + } + { + typedef multi_index_container< + pair_of_ints, + indexed_by< + hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>, + random_access<>, + ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> > > + int_int_set; + + int_int_set iis; + nth_index<int_int_set,1>::type& ii1=get<1>(iis); + int_int_set::iterator p1=iis.insert(pair_of_ints(0,0)).first; + int_int_set::iterator p2=iis.insert(pair_of_ints(5,5)).first; + int_int_set::iterator p3=iis.insert(pair_of_ints(10,10)).first; + + BOOST_TEST(!iis.replace(p1,pair_of_ints(5,0))); + BOOST_TEST(!ii1.replace(ii1.begin(),pair_of_ints(0,5))); + BOOST_TEST(!iis.replace(p1,pair_of_ints(5,11))); + BOOST_TEST(!iis.replace(p1,pair_of_ints(11,5))); + BOOST_TEST(!iis.replace(p2,pair_of_ints(10,5))); + BOOST_TEST(!iis.replace(p2,pair_of_ints(5,10))); + BOOST_TEST(!iis.replace(p3,pair_of_ints(5,10))); + BOOST_TEST(!ii1.replace(boost::prior(ii1.end()),pair_of_ints(10,5))); + + BOOST_TEST(iis.modify(p1,increment_first)); + BOOST_TEST(ii1.modify(ii1.begin(),increment_first)); + BOOST_TEST(iis.modify(p1,increment_first)); + BOOST_TEST(ii1.modify(ii1.begin(),increment_first,decrement_first)); + + BOOST_TEST(!iis.modify(p1,increment_first,decrement_first)); + BOOST_TEST(iis.size()==3); + + BOOST_TEST(!iis.modify(p1,increment_first)); + BOOST_TEST(iis.size()==2); + + p1=iis.insert(pair_of_ints(0,0)).first; + BOOST_TEST(ii1.modify(boost::prior(ii1.end()),increment_second)); + BOOST_TEST(iis.modify(p1,increment_second,decrement_second)); + BOOST_TEST(ii1.modify(boost::prior(ii1.end()),increment_second)); + BOOST_TEST(iis.modify(p1,increment_second)); + + BOOST_TEST(!ii1.modify( + boost::prior(ii1.end()),increment_second,decrement_second)); + BOOST_TEST(ii1.size()==3); + + BOOST_TEST(!ii1.modify(boost::prior(ii1.end()),increment_second)); + BOOST_TEST(ii1.size()==2); + } + { + typedef multi_index_container< + int, + indexed_by< + ordered_non_unique<identity<int> > + > + > int_multiset; + test_stable_update<int_multiset>(); + + typedef multi_index_container< + int, + indexed_by< + hashed_unique<identity<int> > + > + > int_hashed_set; + test_stable_update<int_hashed_set>(); + + typedef multi_index_container< + int, + indexed_by< + hashed_unique<identity<int> > + > + > int_hashed_multiset; + test_stable_update<int_hashed_multiset>(); + + typedef multi_index_container< + int, + indexed_by< + hashed_unique<identity<int>,null_hash> + > + > degenerate_int_hashed_set; + test_stable_update<degenerate_int_hashed_set>(); + + typedef multi_index_container< + int, + indexed_by< + hashed_non_unique<identity<int>,null_hash> + > + > degenerate_int_hashed_multiset; + test_stable_update<degenerate_int_hashed_multiset>(); + } +} diff --git a/src/boost/libs/multi_index/test/test_update.hpp b/src/boost/libs/multi_index/test/test_update.hpp new file mode 100644 index 000000000..ec7424b64 --- /dev/null +++ b/src/boost/libs/multi_index/test/test_update.hpp @@ -0,0 +1,11 @@ +/* Boost.MultiIndex test for replace(), modify() and modify_key(). + * + * Copyright 2003-2008 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/multi_index for library home page. + */ + +void test_update(); diff --git a/src/boost/libs/multi_index/test/test_update_main.cpp b/src/boost/libs/multi_index/test/test_update_main.cpp new file mode 100644 index 000000000..4fa2dba1b --- /dev/null +++ b/src/boost/libs/multi_index/test/test_update_main.cpp @@ -0,0 +1,18 @@ +/* Boost.MultiIndex test for replace(), modify() and modify_key(). + * + * Copyright 2003-2013 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/multi_index for library home page. + */ + +#include <boost/detail/lightweight_test.hpp> +#include "test_update.hpp" + +int main() +{ + test_update(); + return boost::report_errors(); +} diff --git a/src/boost/libs/multi_index/test_results.svg b/src/boost/libs/multi_index/test_results.svg new file mode 100644 index 000000000..d3d613ffd --- /dev/null +++ b/src/boost/libs/multi_index/test_results.svg @@ -0,0 +1,26 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="95" height="20"> + <linearGradient id="b" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1"/> + <stop offset="1" stop-opacity=".1"/> + </linearGradient> + <clipPath id="a"> + <rect width="95" height="20" rx="3" fill="#fff"/> + </clipPath> + <g clip-path="url(#a)"> + <path fill="#555" d="M0 0h48v20H0z"/> + <path fill="#4c1" d="M48 0h47v20H48z"/> + <path fill="url(#b)" d="M0 0h95v20H0z"/> + </g> + <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> + <path fill="#fff" d="M 10.8566 9.70598 l -3.60307 0 l -0.0903426 0.15447 l -1.63598 2.79514 l -0.0919027 0.156812 l 0.0912783 0.157278 l 1.63599 2.82198 l 0.0901858 0.155564 l 3.60291 0 l 0.090498 -0.153378 l 1.64956 -2.79498 l 0.093151 -0.157907 l -0.0923709 -0.158212 l -1.64956 -2.82213 l -0.0903415 -0.154627 z m -5.06008 3.1072 l 1.63598 -2.79514 l 3.24498 0 l 1.64956 2.82213 l -1.64956 2.79498 l -3.24498 0 l -1.63598 -2.82198 z"/> + <path fill="#fff" d="M 16.6973 6.54947 l -3.6026 0 l -0.090185 0.155562 l -1.54689 2.67 l -0.0906544 0.156655 l 0.0908101 0.1565 l 1.72508 2.97067 l 0.0908101 0.156188 l 0.180528 -0.000780746 l 3.06679 -0.0137328 l 0.178187 -0.000780746 l 0.0898736 -0.153845 l 1.65658 -2.83383 l 0.0926823 -0.158528 l -0.093773 -0.15806 l -1.65658 -2.79311 l -0.0906529 -0.15291 z m -4.96959 2.98206 l 1.54689 -2.67 l 3.24498 0 l 1.65658 2.79311 l -1.65658 2.83383 l -3.06679 0.0137328 l -1.72508 -2.97067 z"/> + <path fill="#fff" d="M 12.4576 4.03269 l -3.56874 0 l -0.0898744 0.156967 l -1.61336 2.81683 l -0.0875335 0.152755 l 0.0855053 0.153848 l 0.991265 1.78437 l 0.0887818 0.160088 l 0.183024 0.000468606 l 2.38603 0.00686454 l 0.178812 0.000468606 l 0.0909666 -0.154003 l 1.72804 -2.92995 l 0.850837 0 l -0.265721 -0.466534 l -0.868311 -1.52458 l -0.0897187 -0.15759 z m -5.00126 3.12889 l 1.61336 -2.81683 l 3.20644 0 l 0.868313 1.52458 l -0.492278 0 l -1.81854 3.08348 l -2.38603 -0.00686454 l -0.991265 -1.78437 z"/> + <path fill="#cccccc" d="M 10.8566 9.70598 m -5.06008 3.1072 l 1.63598 -2.79514 l 3.24498 0 l 1.64956 2.82213 l -1.64956 2.79498 l -3.24498 0 l -1.63598 -2.82198 z"/> + <path fill="#cccccc" d="M 16.6973 6.54947 m -4.96959 2.98206 l 1.54689 -2.67 l 3.24498 0 l 1.65658 2.79311 l -1.65658 2.83383 l -3.06679 0.0137328 l -1.72508 -2.97067 z"/> + <path fill="#cccccc" d="M 12.4576 4.03269 m -5.00126 3.12889 l 1.61336 -2.81683 l 3.20644 0 l 0.868313 1.52458 l -0.492278 0 l -1.81854 3.08348 l -2.38603 -0.00686454 l -0.991265 -1.78437 z"/> + <text x="335" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">test</text> + <text x="335" y="140" transform="scale(.1)" textLength="210">test</text> + <text x="705" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">results</text> + <text x="705" y="140" transform="scale(.1)" textLength="370">results</text> + </g> +</svg>
\ No newline at end of file |