From 3af96e0801773e6cb917f58541093806a1a9fa27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 24 Sep 2014 16:09:56 +0200 Subject: [PATCH] Implements N3644. - Avoid deriving from std::iterator_traits as iterators become too fat. - Use intrusive's reverse_iterator some std::reverse_iterator-s don't value initialize base. --- bench/detail/varray.hpp | 11 +- doc/container.qbk | 25 +++- include/boost/container/deque.hpp | 6 +- include/boost/container/detail/flat_tree.hpp | 10 +- include/boost/container/detail/iterators.hpp | 14 +- include/boost/container/detail/tree.hpp | 8 +- include/boost/container/list.hpp | 4 +- include/boost/container/stable_vector.hpp | 5 +- include/boost/container/string.hpp | 4 +- include/boost/container/vector.hpp | 10 +- proj/vc7ide/container.sln | 14 +- proj/vc7ide/null_iterators_test.vcproj | 128 +++++++++++++++++++ test/expand_bwd_test_template.hpp | 2 +- test/null_iterators_test.cpp | 97 ++++++++++++++ test/scoped_allocator_adaptor_test.cpp | 2 +- 15 files changed, 298 insertions(+), 42 deletions(-) create mode 100644 proj/vc7ide/null_iterators_test.vcproj create mode 100644 test/null_iterators_test.cpp diff --git a/bench/detail/varray.hpp b/bench/detail/varray.hpp index 005251d..244c34d 100644 --- a/bench/detail/varray.hpp +++ b/bench/detail/varray.hpp @@ -19,6 +19,8 @@ #include #include +#include + #include "varray_util.hpp" #ifndef BOOST_NO_EXCEPTIONS @@ -36,7 +38,6 @@ #include #include -#include /** * @defgroup varray_non_member varray non-member functions @@ -267,9 +268,9 @@ public: //! @brief The const iterator type. typedef const_pointer const_iterator; //! @brief The reverse iterator type. - typedef std::reverse_iterator reverse_iterator; + typedef container_detail::reverse_iterator reverse_iterator; //! @brief The const reverse iterator. - typedef std::reverse_iterator const_reverse_iterator; + typedef container_detail::reverse_iterator const_reverse_iterator; //! @brief The type of a strategy used by the varray. typedef Strategy strategy_type; @@ -1895,8 +1896,8 @@ public: typedef pointer iterator; typedef const_pointer const_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; + typedef container_detail::reverse_iterator reverse_iterator; + typedef container_detail::reverse_iterator const_reverse_iterator; // nothrow varray() {} diff --git a/doc/container.qbk b/doc/container.qbk index 9704d89..8208308 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -712,7 +712,7 @@ Use them simply specifying the new allocator in the corresponding template argum [endsect] -[section:Cpp11_conformance C++11 Conformance] +[section:Cpp11_conformance C++11/C++14 Conformance] [*Boost.Container] aims for full C++11 conformance except reasoned deviations, backporting as much as possible for C++03. Obviously, this conformance is a work @@ -807,7 +807,28 @@ implements the C++11 changes that were specified in [@http://www.open-std.org/jt [section:initializer_lists Initializer lists] [*Boost.Container] supports initialization, assignments and insertions from initializer lists -but only in compilers that implement this feature. +in compilers that implement this feature. + +[endsect] + +[section:null_iterators Null Forward Iterators] + +[*Boost.Container] implements +[@http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3644.pdf C++14 Null Forward Iterators], +which means that value-initialized iterators may be compared and compare equal +to other value-initialized iterators of the same type. Value initialized iterators behave as if they refer +past the end of the same empty sequence (example taken from N3644): + +[c++] + + vector v = { ... }; + auto ni = vector::iterator(); + auto nd = vector::iterator(); + ni == ni; // True. + nd != nd; // False. + v.begin() == ni; // ??? (likely false in practice). + v.end() == ni; // ??? (likely false in practice). + ni == nd; // Won’t compile. [endsect] diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 56277bd..c5f7994 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -146,7 +146,7 @@ class deque_iterator {} deque_iterator() BOOST_CONTAINER_NOEXCEPT - : m_cur(), m_first(), m_last(), m_node() + : m_cur(), m_first(), m_last(), m_node() //Value initialization to achieve "null iterators" (N3644) {} deque_iterator(deque_iterator const& x) BOOST_CONTAINER_NOEXCEPT @@ -504,8 +504,8 @@ class deque : protected deque_base typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type; typedef BOOST_CONTAINER_IMPDEF(typename Base::iterator) iterator; typedef BOOST_CONTAINER_IMPDEF(typename Base::const_iterator) const_iterator; - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) const_reverse_iterator; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp index 36130b7..a6f7568 100644 --- a/include/boost/container/detail/flat_tree.hpp +++ b/include/boost/container/detail/flat_tree.hpp @@ -85,13 +85,15 @@ struct get_flat_tree_iterators pointer_traits:: template rebind_pointer::type const_iterator; #else //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER - typedef typename container_detail:: + typedef typename boost::container::container_detail:: vec_iterator iterator; - typedef typename container_detail:: + typedef typename boost::container::container_detail:: vec_iterator const_iterator; #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; + typedef boost::container::container_detail:: + reverse_iterator reverse_iterator; + typedef boost::container::container_detail:: + reverse_iterator const_reverse_iterator; }; template #include -#include #include #include #include +#include +#include #ifdef BOOST_CONTAINER_PERFECT_FORWARDING #include @@ -745,14 +746,15 @@ struct std_iterator template class iterator - : public std_iterator::type { typedef typename std_iterator::type types_t; public: - typedef typename types_t::value_type value_type; - typedef typename types_t::pointer pointer; - typedef typename types_t::reference reference; + typedef typename types_t::pointer pointer; + typedef typename types_t::reference reference; + typedef typename types_t::difference_type difference_type; + typedef typename types_t::iterator_category iterator_category; + typedef typename types_t::value_type value_type; iterator() {} @@ -808,6 +810,8 @@ class iterator IIterator m_iit; }; +using ::boost::intrusive::detail::reverse_iterator; + } //namespace container_detail { } //namespace container { } //namespace boost { diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 1a0b155..b5600dd 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -515,10 +515,10 @@ class tree typedef key_node_compare KeyNodeCompare; public: - typedef container_detail::iterator iterator; - typedef container_detail::iterator const_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; + typedef container_detail::iterator iterator; + typedef container_detail::iterator const_iterator; + typedef container_detail::reverse_iterator reverse_iterator; + typedef container_detail::reverse_iterator const_reverse_iterator; tree() : AllocHolder(ValComp(key_compare())) diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 1863b5f..0b99e1e 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -199,8 +199,8 @@ class list typedef BOOST_CONTAINER_IMPDEF(NodeAlloc) stored_allocator_type; typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) const_reverse_iterator; ////////////////////////////////////////////// // diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index cf3b177..97c105c 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -265,6 +265,7 @@ class stable_vector_iterator {} stable_vector_iterator() BOOST_CONTAINER_NOEXCEPT + : m_pn() //Value initialization to achieve "null iterators" (N3644) {} stable_vector_iterator(stable_vector_iterator const& other) BOOST_CONTAINER_NOEXCEPT @@ -504,8 +505,8 @@ class stable_vector typedef node_allocator_type stored_allocator_type; typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) const_reverse_iterator; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp index 242e9dd..bb0cc05 100644 --- a/include/boost/container/string.hpp +++ b/include/boost/container/string.hpp @@ -539,8 +539,8 @@ class basic_string typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type; typedef BOOST_CONTAINER_IMPDEF(pointer) iterator; typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator; - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) const_reverse_iterator; static const size_type npos = size_type(-1); #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index dee986c..784203e 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -102,11 +102,7 @@ class vec_iterator //Constructors vec_iterator() BOOST_CONTAINER_NOEXCEPT - #ifndef NDEBUG - : m_ptr() - #else - // No value initialization of m_ptr() to speed up things a bit: - #endif + : m_ptr() //Value initialization to achieve "null iterators" (N3644) {} vec_iterator(vec_iterator const& other) BOOST_CONTAINER_NOEXCEPT @@ -573,8 +569,8 @@ class vector typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; #endif - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(std::reverse_iterator) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator) const_reverse_iterator; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: diff --git a/proj/vc7ide/container.sln b/proj/vc7ide/container.sln index a5fbb74..a4489cb 100644 --- a/proj/vc7ide/container.sln +++ b/proj/vc7ide/container.sln @@ -171,6 +171,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "insert_vs_emplace_test", "i ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "null_iterators_test", "null_iterators_test.vcproj", "{C90520E3-B8A9-EB54-76E2-25DFA3C7762A}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -347,10 +351,12 @@ Global {5C2D1813-24CE-A826-4FE5-5732251A3FAF}.Debug.Build.0 = Debug|Win32 {5C2D1813-24CE-A826-4FE5-5732251A3FAF}.Release.ActiveCfg = Release|Win32 {5C2D1813-24CE-A826-4FE5-5732251A3FAF}.Release.Build.0 = Release|Win32 - {5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Debug.ActiveCfg = Debug|Win32 - {5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Debug.Build.0 = Debug|Win32 - {5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Release.ActiveCfg = Release|Win32 - {5E1C1C23-26A9-4FE5-A24E-DA735271C32B}.Release.Build.0 = Release|Win32 + {A1C1C223-26A9-A20E-4CE5-D3325271A7CB}.Debug.ActiveCfg = Debug|Win32 + {A1C1C223-26A9-A20E-4CE5-D3325271A7CB}.Release.ActiveCfg = Release|Win32 + {C90520E3-B8A9-EB54-76E2-25DFA3C7762A}.Debug.ActiveCfg = Debug|Win32 + {C90520E3-B8A9-EB54-76E2-25DFA3C7762A}.Debug.Build.0 = Debug|Win32 + {C90520E3-B8A9-EB54-76E2-25DFA3C7762A}.Release.ActiveCfg = Release|Win32 + {C90520E3-B8A9-EB54-76E2-25DFA3C7762A}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/null_iterators_test.vcproj b/proj/vc7ide/null_iterators_test.vcproj new file mode 100644 index 0000000..db5735f --- /dev/null +++ b/proj/vc7ide/null_iterators_test.vcproj @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/expand_bwd_test_template.hpp b/test/expand_bwd_test_template.hpp index b86650b..7d6486d 100644 --- a/test/expand_bwd_test_template.hpp +++ b/test/expand_bwd_test_template.hpp @@ -86,7 +86,7 @@ bool test_insert_with_expand_bwd() value_type *memory = (value_type*)memptr.get(); std::vector initial_data; initial_data.resize(InitialSize[iteration]); - for(int i = 0; i < InitialSize[iteration]; ++i){ + for(unsigned int i = 0; i < InitialSize[iteration]; ++i){ initial_data[i] = i; } diff --git a/test/null_iterators_test.cpp b/test/null_iterators_test.cpp new file mode 100644 index 0000000..7bf4b81 --- /dev/null +++ b/test/null_iterators_test.cpp @@ -0,0 +1,97 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace boost::container; + +typedef boost::aligned_storage::type buffer_t; + +static buffer_t buffer_0x00; +static buffer_t buffer_0xFF; + +template +const Iterator &on_0x00_buffer() +{ + BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator)); + return * ::new(std::memset(&buffer_0x00, 0x00, sizeof(buffer_0x00))) Iterator(); +} + +template +const Iterator &on_0xFF_buffer() +{ + BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator)); + return * ::new(std::memset(&buffer_0xFF, 0xFF, sizeof(buffer_0xFF))) Iterator(); +} + +namespace boost { +namespace container { +namespace test { + +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reverse_iterator) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reverse_iterator) + +}}} //namespace boost::container::test { + +template +void check_null_iterators() +{ + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT + (boost::container::test::, Container + ,reverse_iterator, iterator) reverse_iterator; + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT + (boost::container::test::, Container + ,const_reverse_iterator, const_iterator) const_reverse_iterator; + + BOOST_TEST(on_0xFF_buffer() == on_0x00_buffer()); + BOOST_TEST(on_0xFF_buffer() == on_0x00_buffer()); + BOOST_TEST(on_0xFF_buffer() == on_0x00_buffer()); + BOOST_TEST(on_0xFF_buffer() == on_0x00_buffer()); +} + +int main() +{ + check_null_iterators< vector >(); + check_null_iterators< deque >(); + check_null_iterators< stable_vector >(); + check_null_iterators< static_vector >(); + check_null_iterators< string >(); + check_null_iterators< list >(); + check_null_iterators< slist >(); + check_null_iterators< map >(); + check_null_iterators< multimap >(); + check_null_iterators< set >(); + check_null_iterators< multiset >(); + check_null_iterators< flat_set >(); + check_null_iterators< flat_multiset >(); + check_null_iterators< flat_map >(); + check_null_iterators< flat_multimap >(); + + return boost::report_errors(); +} diff --git a/test/scoped_allocator_adaptor_test.cpp b/test/scoped_allocator_adaptor_test.cpp index 58b6ee8..425e295 100644 --- a/test/scoped_allocator_adaptor_test.cpp +++ b/test/scoped_allocator_adaptor_test.cpp @@ -115,7 +115,7 @@ enum ConstructionTypeEnum { ConstructiblePrefix, ConstructibleSuffix, - NotUsesAllocator, + NotUsesAllocator }; //This base class provices types for