diff --git a/include/boost/intrusive/pack_options.hpp b/include/boost/intrusive/pack_options.hpp new file mode 100644 index 0000000..7d282dd --- /dev/null +++ b/include/boost/intrusive/pack_options.hpp @@ -0,0 +1,370 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-2013 +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP +#define BOOST_INTRUSIVE_PACK_OPTIONS_HPP + +#include + +namespace boost { +namespace intrusive { + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +#if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + +template +struct do_pack +{ + //Use "pack" member template to pack options + typedef typename Next::template pack type; +}; + +template +struct do_pack +{ + //Avoid packing "void" to shorten template names + typedef Prev type; +}; + +template + < class DefaultOptions + , class O1 = void + , class O2 = void + , class O3 = void + , class O4 = void + , class O5 = void + , class O6 = void + , class O7 = void + , class O8 = void + , class O9 = void + , class O10 = void + , class O11 = void + > +struct pack_options +{ + // join options + typedef + typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < DefaultOptions + , O1 + >::type + , O2 + >::type + , O3 + >::type + , O4 + >::type + , O5 + >::type + , O6 + >::type + , O7 + >::type + , O8 + >::type + , O9 + >::type + , O10 + >::type + , O11 + >::type + type; +}; +#else + +//index_tuple +template +struct index_tuple{}; + +//build_number_seq +template > +struct build_number_seq; + +template +struct build_number_seq > + : build_number_seq > +{}; + +template +struct build_number_seq<0, index_tuple > +{ typedef index_tuple type; }; + +template +struct typelist +{}; + +//invert_typelist +template +struct invert_typelist; + +template +struct typelist_element; + +template +struct typelist_element > +{ + typedef typename typelist_element >::type type; +}; + +template +struct typelist_element<0, typelist > +{ + typedef Head type; +}; + +template +typelist >::type...> + inverted_typelist(index_tuple, typelist) +{ + return typelist >::type...>(); +} + +//sizeof_typelist +template +struct sizeof_typelist; + +template +struct sizeof_typelist< typelist > +{ + static const std::size_t value = sizeof...(Types); +}; + +//invert_typelist_impl +template +struct invert_typelist_impl; + + +template +struct invert_typelist_impl< Typelist, index_tuple > +{ + static const std::size_t last_idx = sizeof_typelist::value - 1; + typedef typelist + ::type...> type; +}; + +template +struct invert_typelist_impl< Typelist, index_tuple > +{ + typedef Typelist type; +}; + +template +struct invert_typelist_impl< Typelist, index_tuple<> > +{ + typedef Typelist type; +}; + +//invert_typelist +template +struct invert_typelist; + +template +struct invert_typelist< typelist > +{ + typedef typelist typelist_t; + typedef typename build_number_seq::type indexes_t; + typedef typename invert_typelist_impl::type type; +}; + +//Do pack +template +struct do_pack; + +template<> +struct do_pack >; + +template +struct do_pack > +{ + typedef Prev type; +}; + +template +struct do_pack > +{ + typedef typename Prev::template pack type; +}; + +template +struct do_pack > +{ + typedef typename Prev::template pack + >::type> type; +}; + + +template +struct pack_options +{ + typedef typelist typelist_t; + typedef typename invert_typelist::type inverted_typelist; + typedef typename do_pack::type type; +}; + +#endif //!defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) + +#define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) \ +template< class TYPE> \ +struct OPTION_NAME \ +{ \ + template \ + struct pack : Base \ + { \ + typedef TYPEDEF_EXPR TYPEDEF_NAME; \ + }; \ +}; \ +// + +#define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) \ +template< TYPE VALUE> \ +struct OPTION_NAME \ +{ \ + template \ + struct pack : Base \ + { \ + static const TYPE CONSTANT_NAME = VALUE; \ + }; \ +}; \ +// + +#else //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + +//! This class is a utility that takes: +//! - a default options class defining initial static constant +//! and typedefs +//! - several options defined with BOOST_INTRUSIVE_OPTION_CONSTANT and +//! BOOST_INTRUSIVE_OPTION_TYPE +//! +//! and packs them together in a new type that defines all options as +//! member typedefs or static constant values. Given options of form: +//! +//! \code +//! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, VoidPointer, my_pointer_type) +//! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) +//! \endcode +//! +//! the following expression +//! +//! \code +//! +//! struct default_options +//! { +//! typedef long int_type; +//! static const int int_constant = -1; +//! }; +//! +//! pack_options< default_options, my_pointer, incremental >::type +//! \endcode +//! +//! will create a type that will contain the following typedefs/constants +//! +//! \code +//! struct unspecified_type +//! { +//! //Default options +//! typedef long int_type; +//! static const int int_constant = -1; +//! +//! //Packed options (will ovewrite any default option) +//! typedef void* my_pointer_type; +//! static const bool is_incremental = true; +//! }; +//! \endcode +//! +//! If an option is specified in the default options argument and later +//! redefined as an option, the last definition will prevail. +template +struct pack_options +{ + typedef unspecified_type type; +}; + +//! Defines an option class of name OPTION_NAME that can be used to specify a type +//! of type TYPE... +//! +//! \code +//! struct OPTION_NAME +//! { /*unspecified_content*/ }; +//! \endcode +//! +//! ...that after being combined with +//! boost::intrusive::pack_options, +//! will typedef TYPE as a typedef of name TYPEDEF_NAME. Example: +//! +//! \code +//! //[includes and namespaces omitted for brevity] +//! +//! //This macro will create the following class: +//! // template +//! // struct my_pointer +//! // { unspecified_content }; +//! BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, boost::remove_pointer::type, my_pointer_type) +//! +//! struct empty_default{}; +//! +//! typedef pack_options< empty_default, typename my_pointer >::type::my_pointer_type type; +//! +//! BOOST_STATIC_ASSERT(( boost::is_same::value )); +//! +//! \endcode +#define BOOST_INTRUSIVE_OPTION_TYPE(OPTION_NAME, TYPE, TYPEDEF_EXPR, TYPEDEF_NAME) + +//! Defines an option class of name OPTION_NAME that can be used to specify a constant +//! of type TYPE with value VALUE... +//! +//! \code +//! struct OPTION_NAME +//! { /*unspecified_content*/ }; +//! \endcode +//! +//! ...that after being combined with +//! boost::intrusive::pack_options, +//! will contain a CONSTANT_NAME static constant of value VALUE. Example: +//! +//! \code +//! //[includes and namespaces omitted for brevity] +//! +//! //This macro will create the following class: +//! // template +//! // struct incremental +//! // { unspecified_content }; +//! BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) +//! +//! struct empty_default{}; +//! +//! const bool is_incremental = pack_options< empty_default, incremental >::type::is_incremental; +//! +//! BOOST_STATIC_ASSERT(( is_incremental == true )); +//! +//! \endcode +#define BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) + +#endif //#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + +} //namespace intrusive { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTRUSIVE_PACK_OPTIONS_HPP diff --git a/proj/vc7ide/Intrusive.ncb b/proj/vc7ide/Intrusive.ncb new file mode 100644 index 0000000..f32ffe7 Binary files /dev/null and b/proj/vc7ide/Intrusive.ncb differ diff --git a/proj/vc7ide/Intrusive.suo b/proj/vc7ide/Intrusive.suo new file mode 100644 index 0000000..62883c2 Binary files /dev/null and b/proj/vc7ide/Intrusive.suo differ diff --git a/proj/vc7ide/container_size_test/container_size_test.vcproj b/proj/vc7ide/container_size_test/container_size_test.vcproj new file mode 100644 index 0000000..dad1be0 --- /dev/null +++ b/proj/vc7ide/container_size_test/container_size_test.vcproj @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/pack_options/pack_options.vcproj b/proj/vc7ide/pack_options/pack_options.vcproj new file mode 100644 index 0000000..6da13c6 --- /dev/null +++ b/proj/vc7ide/pack_options/pack_options.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/container_size_test.cpp b/test/container_size_test.cpp new file mode 100644 index 0000000..d95cee5 --- /dev/null +++ b/test/container_size_test.cpp @@ -0,0 +1,187 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014 +// +// 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/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace boost::intrusive; + +template +struct boolean +{ + static const bool value = Value; +}; + +template +struct pow2_and_equal_sizes +{ + static const std::size_t a_size = sizeof(A); + static const std::size_t b_size = sizeof(B); + static const bool a_b_sizes_equal = a_size == b_size; + static const bool value = !(a_size & (a_size - 1u)); +}; + +template +struct node : Hook +{}; + +//Avoid testing for uncommon architectures +void test_sizes(boolean, std::size_t) +{} + +template +void test_iterator_sizes(C &, std::size_t size) +{ + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + BOOST_TEST_EQ(sizeof(iterator), size); + BOOST_TEST_EQ(sizeof(const_iterator), size); +} + +//Test sizes for common 32 and 64 bit architectures +void test_sizes(boolean, std::size_t wordsize) +{ + { //list + list > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { + list > >, constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize); + } + { //slist + slist > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize); + } + { + slist > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*1); + test_iterator_sizes(c, wordsize); + } + { + slist > > , cache_last > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //set + set > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*5); + test_iterator_sizes(c, wordsize); + } + { + set > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + set > > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //avl + avl_set > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*5); + test_iterator_sizes(c, wordsize); + } + { + avl_set > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + avl_set > > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //splay + splay_set > > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + splay_set > > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //scapegoat + sg_set > > c; + BOOST_TEST_EQ(sizeof(c), (wordsize*5+sizeof(float)*2)); + test_iterator_sizes(c, wordsize); + } + { //treap + treap_set > > c; + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize); + } + { + treap_set > , constant_time_size > c; + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize); + } + { //unordered + typedef unordered_set > > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set > , power_2_buckets > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*3); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set >, constant_time_size > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set > >, constant_time_size > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*2); + test_iterator_sizes(c, wordsize*2); + } + { + typedef unordered_set > >, incremental > cont_type; + cont_type::bucket_type buckets[1]; + cont_type c(cont_type::bucket_traits(buckets, 1)); + BOOST_TEST_EQ(sizeof(c), wordsize*4); + test_iterator_sizes(c, wordsize*2); + } +} + +int main() +{ + test_sizes(boolean< pow2_and_equal_sizes::value >(), sizeof(std::size_t)); + return ::boost::report_errors(); +} + +#include diff --git a/test/pack_options_test.cpp b/test/pack_options_test.cpp new file mode 100644 index 0000000..2f0ef09 --- /dev/null +++ b/test/pack_options_test.cpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-2013. 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/intrusive for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include + +struct empty_default{}; + +using namespace boost::intrusive; + +//Test BOOST_INTRUSIVE_OPTION_CONSTANT +BOOST_INTRUSIVE_OPTION_CONSTANT(incremental, bool, Enabled, is_incremental) +const bool is_incremental_value = pack_options< empty_default, incremental >::type::is_incremental; +BOOST_STATIC_ASSERT(( is_incremental_value == true )); + +//Test BOOST_INTRUSIVE_OPTION_TYPE +BOOST_INTRUSIVE_OPTION_TYPE(my_pointer, VoidPointer, typename boost::remove_pointer::type, my_pointer_type) +typedef pack_options< empty_default, my_pointer >::type::my_pointer_type my_pointer_type; +BOOST_STATIC_ASSERT(( boost::is_same::value )); + +//test combination of BOOST_INTRUSIVE_OPTION_CONSTANT and BOOST_INTRUSIVE_OPTION_TYPE +// First add new options +struct default_options +{ + static const long long_constant = -3; + typedef double * double_typedef; +}; + +BOOST_INTRUSIVE_OPTION_CONSTANT(incremental2, bool, Enabled, is_incremental2) +BOOST_INTRUSIVE_OPTION_TYPE(my_pointer2, VoidPointer, typename boost::add_pointer::type, my_pointer_type2) +typedef pack_options < default_options + , incremental + , my_pointer + , incremental2 + , my_pointer2 + >::type combined_type; +BOOST_STATIC_ASSERT(( combined_type::is_incremental == false )); +BOOST_STATIC_ASSERT(( combined_type::is_incremental2 == true )); +BOOST_STATIC_ASSERT(( boost::is_same::value )); +BOOST_STATIC_ASSERT(( boost::is_same::value )); + +//test packing the default options leads to a default options type +BOOST_STATIC_ASSERT(( boost::is_same::type, default_options>::value )); + +int main() +{ + return 0; +} + +#include