diff --git a/docs/changes.txt b/docs/changes.txt index 7fc8529dd027..f4867d6ac6fe 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -64,6 +64,14 @@ Changes in behaviour which may result in build errors wxGraphicsContext::CreatePen() continues to compile and work as before. +3.1.2: (released 2018-??-??) +---------------------------- + +All: + +- Make wxList and wxVector iterators conform to input iterator requirements. + + 3.1.1: (released 2018-02-19) ---------------------------- diff --git a/include/wx/list.h b/include/wx/list.h index 427c0392f639..22446a2dd460 100644 --- a/include/wx/list.h +++ b/include/wx/list.h @@ -599,6 +599,17 @@ friend class wxHashTableBase; // should be able to call untyped Find() // macros for definition of "template" list type // ----------------------------------------------------------------------------- +// Helper macro defining common iterator typedefs +#if wxUSE_STD_CONTAINERS_COMPATIBLY + #include + + #define WX_DECLARE_LIST_ITER_DIFF_AND_CATEGORY() \ + typedef std::ptrdiff_t difference_type; \ + typedef std::bidirectional_iterator_tag iterator_category; +#else + #define WX_DECLARE_LIST_ITER_DIFF_AND_CATEGORY() +#endif + // and now some heavy magic... // declare a list type named 'name' and containing elements of type 'T *' @@ -761,19 +772,21 @@ friend class wxHashTableBase; // should be able to call untyped Find() \ classexp iterator \ { \ - typedef name list; \ public: \ - typedef nodetype Node; \ - typedef iterator itor; \ + WX_DECLARE_LIST_ITER_DIFF_AND_CATEGORY() \ typedef T* value_type; \ - typedef value_type* ptr_type; \ + typedef value_type* pointer; \ typedef value_type& reference; \ \ + typedef nodetype Node; \ + typedef iterator itor; \ + \ Node* m_node; \ Node* m_init; \ public: \ + /* Compatibility typedefs, don't use */ \ typedef reference reference_type; \ - typedef ptr_type pointer_type; \ + typedef pointer pointer_type; \ \ iterator(Node* node, Node* init) : m_node(node), m_init(init) {}\ iterator() : m_node(NULL), m_init(NULL) { } \ @@ -811,19 +824,20 @@ friend class wxHashTableBase; // should be able to call untyped Find() }; \ classexp const_iterator \ { \ - typedef name list; \ public: \ - typedef nodetype Node; \ + WX_DECLARE_LIST_ITER_DIFF_AND_CATEGORY() \ typedef T* value_type; \ - typedef const value_type& const_reference; \ + typedef const value_type* pointer; \ + typedef const value_type& reference; \ + \ + typedef nodetype Node; \ typedef const_iterator itor; \ - typedef value_type* ptr_type; \ \ Node* m_node; \ Node* m_init; \ public: \ - typedef const_reference reference_type; \ - typedef const ptr_type pointer_type; \ + typedef reference reference_type; \ + typedef pointer pointer_type; \ \ const_iterator(Node* node, Node* init) \ : m_node(node), m_init(init) { } \ @@ -864,19 +878,20 @@ friend class wxHashTableBase; // should be able to call untyped Find() }; \ classexp reverse_iterator \ { \ - typedef name list; \ public: \ - typedef nodetype Node; \ + WX_DECLARE_LIST_ITER_DIFF_AND_CATEGORY() \ typedef T* value_type; \ - typedef reverse_iterator itor; \ - typedef value_type* ptr_type; \ + typedef value_type* pointer; \ typedef value_type& reference; \ \ + typedef nodetype Node; \ + typedef reverse_iterator itor; \ + \ Node* m_node; \ Node* m_init; \ public: \ typedef reference reference_type; \ - typedef ptr_type pointer_type; \ + typedef pointer pointer_type; \ \ reverse_iterator(Node* node, Node* init) \ : m_node(node), m_init(init) { } \ @@ -903,19 +918,20 @@ friend class wxHashTableBase; // should be able to call untyped Find() }; \ classexp const_reverse_iterator \ { \ - typedef name list; \ public: \ - typedef nodetype Node; \ + WX_DECLARE_LIST_ITER_DIFF_AND_CATEGORY() \ typedef T* value_type; \ + typedef const value_type* pointer; \ + typedef const value_type& reference; \ + \ + typedef nodetype Node; \ typedef const_reverse_iterator itor; \ - typedef value_type* ptr_type; \ - typedef const value_type& const_reference; \ \ Node* m_node; \ Node* m_init; \ public: \ - typedef const_reference reference_type; \ - typedef const ptr_type pointer_type; \ + typedef reference reference_type; \ + typedef pointer pointer_type; \ \ const_reverse_iterator(Node* node, Node* init) \ : m_node(node), m_init(init) { } \ diff --git a/include/wx/vector.h b/include/wx/vector.h index e73b1b9514e5..8a7ae1b22813 100644 --- a/include/wx/vector.h +++ b/include/wx/vector.h @@ -33,6 +33,9 @@ inline void wxVectorSort(wxVector& v) #include "wx/meta/if.h" #include "wx/beforestd.h" +#if wxUSE_STD_CONTAINERS_COMPATIBLY +#include +#endif #include // for placement new #include "wx/afterstd.h" @@ -160,7 +163,7 @@ class wxVector public: typedef size_t size_type; - typedef size_t difference_type; + typedef ptrdiff_t difference_type; typedef T value_type; typedef value_type* pointer; typedef const value_type* const_pointer; @@ -172,6 +175,14 @@ class wxVector class reverse_iterator { public: +#if wxUSE_STD_CONTAINERS_COMPATIBLY + typedef std::random_access_iterator_tag iterator_category; +#endif + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + reverse_iterator() : m_ptr(NULL) { } explicit reverse_iterator(iterator it) : m_ptr(it) { } reverse_iterator(const reverse_iterator& it) : m_ptr(it.m_ptr) { } @@ -218,6 +229,14 @@ class wxVector class const_reverse_iterator { public: +#if wxUSE_STD_CONTAINERS_COMPATIBLY + typedef std::random_access_iterator_tag iterator_category; +#endif + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const value_type* pointer; + typedef const value_type& reference; + const_reverse_iterator() : m_ptr(NULL) { } explicit const_reverse_iterator(const_iterator it) : m_ptr(it) { } const_reverse_iterator(const reverse_iterator& it) : m_ptr(it.m_ptr) { } diff --git a/tests/lists/lists.cpp b/tests/lists/lists.cpp index f4b1e3472dce..d19376e7dd4f 100644 --- a/tests/lists/lists.cpp +++ b/tests/lists/lists.cpp @@ -210,3 +210,27 @@ void ListsTestCase::wxListCtorTest() CPPUNIT_ASSERT( Baz::GetNumber() == 0 ); } +#if wxUSE_STD_CONTAINERS_COMPATIBLY + +#include + +// Check that we convert wxList to std::list using the latter's ctor taking 2 +// iterators: this used to be broken in C++11 because wxList iterators didn't +// fully implement input iterator requirements. +TEST_CASE("wxList::iterator", "[list][std][iterator]") +{ + Baz baz1("one"), + baz2("two"); + + wxListBazs li; + li.push_back(&baz1); + li.push_back(&baz2); + + std::list stdli(li.begin(), li.end()); + CHECK( stdli.size() == 2 ); + + const wxListBazs cli; + CHECK( std::list(cli.begin(), cli.end()).empty() ); +} + +#endif // wxUSE_STD_CONTAINERS_COMPATIBLY diff --git a/tests/vectors/vectors.cpp b/tests/vectors/vectors.cpp index 25a9a5cdd596..e3f6734c14c4 100644 --- a/tests/vectors/vectors.cpp +++ b/tests/vectors/vectors.cpp @@ -22,6 +22,10 @@ #include "wx/vector.h" +#if wxUSE_STD_CONTAINERS_COMPATIBLY + #include +#endif // wxUSE_STD_CONTAINERS_COMPATIBLY + // ---------------------------------------------------------------------------- // simple class capable of detecting leaks of its objects // ---------------------------------------------------------------------------- @@ -360,6 +364,13 @@ TEST_CASE("wxVector::reverse_iterator", "[vector][reverse_iterator]") ri = rb + 2; CHECK( ri - rb == 2 ); CHECK( re - ri == 8 ); + +#if wxUSE_STD_CONTAINERS_COMPATIBLY + std::vector stdvec(rb, re); + REQUIRE( stdvec.size() == 10 ); + CHECK( stdvec[0] == 10 ); + CHECK( stdvec[9] == 1 ); +#endif // wxUSE_STD_CONTAINERS_COMPATIBLY } TEST_CASE("wxVector::capacity", "[vector][capacity][shrink_to_fit]")