Skip to content

Commit

Permalink
Merge branch 'iter-concepts'
Browse files Browse the repository at this point in the history
Make wxList and wxVector iterators really iterators from C++ point of
view, by defining all the expected types in them.

See wxWidgets#744
  • Loading branch information
vadz committed Feb 26, 2018
2 parents 813fdca + cc8fccf commit 9f77a4f
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 23 deletions.
8 changes: 8 additions & 0 deletions docs/changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
----------------------------

Expand Down
60 changes: 38 additions & 22 deletions include/wx/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <iterator>

#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 *'
Expand Down Expand Up @@ -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) { } \
Expand Down Expand Up @@ -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) { } \
Expand Down Expand Up @@ -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) { } \
Expand All @@ -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) { } \
Expand Down
21 changes: 20 additions & 1 deletion include/wx/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ inline void wxVectorSort(wxVector<T>& v)
#include "wx/meta/if.h"

#include "wx/beforestd.h"
#if wxUSE_STD_CONTAINERS_COMPATIBLY
#include <iterator>
#endif
#include <new> // for placement new
#include "wx/afterstd.h"

Expand Down Expand Up @@ -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;
Expand All @@ -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) { }
Expand Down Expand Up @@ -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) { }
Expand Down
24 changes: 24 additions & 0 deletions tests/lists/lists.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,27 @@ void ListsTestCase::wxListCtorTest()
CPPUNIT_ASSERT( Baz::GetNumber() == 0 );
}

#if wxUSE_STD_CONTAINERS_COMPATIBLY

#include <list>

// 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<Baz*> stdli(li.begin(), li.end());
CHECK( stdli.size() == 2 );

const wxListBazs cli;
CHECK( std::list<Baz*>(cli.begin(), cli.end()).empty() );
}

#endif // wxUSE_STD_CONTAINERS_COMPATIBLY
11 changes: 11 additions & 0 deletions tests/vectors/vectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@

#include "wx/vector.h"

#if wxUSE_STD_CONTAINERS_COMPATIBLY
#include <vector>
#endif // wxUSE_STD_CONTAINERS_COMPATIBLY

// ----------------------------------------------------------------------------
// simple class capable of detecting leaks of its objects
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -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<int> 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]")
Expand Down

0 comments on commit 9f77a4f

Please sign in to comment.