Tree iterator first commit
This commit is contained in:
parent
5c4cacf286
commit
e05386eafe
4 changed files with 541 additions and 0 deletions
252
include/duckhandy/implem/tree_iterator.inl
Normal file
252
include/duckhandy/implem/tree_iterator.inl
Normal file
|
@ -0,0 +1,252 @@
|
|||
/* Copyright 2016-2024 Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* "duckhandy" is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace dhandy {
|
||||
namespace implem {
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P>
|
||||
bool TreeIterator_base<P>::Exhausted() const {
|
||||
return m_stack.empty();
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P>
|
||||
TreeIterator_base<P>::TreeIterator_base (const TreeIterator_base& parOther) :
|
||||
m_stack(parOther.m_stack)
|
||||
{
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename P>
|
||||
template <typename P1>
|
||||
TreeIterator_base<P>::TreeIterator_base (const TreeIterator_base<P1>& parOther) {
|
||||
typename TreeIterator_base<P1>::StackType otherStackCopy(parOther.m_stack);
|
||||
std::vector<P> localCopy;
|
||||
localCopy.reserve(parOther.m_stack.size());
|
||||
while (not otherStackCopy.empty()) {
|
||||
P convertedItem = otherStackCopy.top();
|
||||
localCopy.push_back(convertedItem);
|
||||
otherStackCopy.pop();
|
||||
}
|
||||
m_stack.reserve(parOther.m_stack.capacity());
|
||||
for (typename std::vector<P>::reverse_iterator itRev = localCopy.rbegin(), itRevEnd = localCopy.rend(); itRev != itRevEnd; ++itRev) {
|
||||
assert(m_stack.capacity() > m_stack.size());
|
||||
m_stack.push(*itRev);
|
||||
}
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
typename TreeIterator_const_layer<T, N, false>::reference TreeIterator_const_layer<T, N, false>::operator* () {
|
||||
assert(not this->Exhausted());
|
||||
return this->m_stack.top()->content;
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
typename TreeIterator_const_layer<T, N, false>::const_reference TreeIterator_const_layer<T, N, false>::operator* () const {
|
||||
assert(not this->Exhausted());
|
||||
return this->m_stack.top()->content;
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
typename TreeIterator_const_layer<T, N, false>::pointer TreeIterator_const_layer<T, N, false>::operator-> () {
|
||||
assert(not this->Exhausted());
|
||||
return &this->m_stack.top()->content;
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
typename TreeIterator_const_layer<T, N, false>::const_pointer TreeIterator_const_layer<T, N, false>::operator-> () const {
|
||||
assert(not this->Exhausted());
|
||||
return &this->m_stack.top()->content;
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
N* TreeIterator_const_layer<T, N, false>::GetPointer() {
|
||||
assert(not this->Exhausted());
|
||||
return this->m_stack.top();
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
const N* TreeIterator_const_layer<T, N, false>::GetPointer() const {
|
||||
assert(not this->Exhausted());
|
||||
return this->m_stack.top();
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
typename TreeIterator_const_layer<T, N, true>::const_reference TreeIterator_const_layer<T, N, true>::operator* () const {
|
||||
assert(not this->Exhausted());
|
||||
return this->m_stack.top()->content;
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
typename TreeIterator_const_layer<T, N, true>::const_pointer TreeIterator_const_layer<T, N, true>::operator-> () const {
|
||||
assert(not this->Exhausted());
|
||||
return &this->m_stack.top()->content;
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------
|
||||
///---------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
const N* TreeIterator_const_layer<T, N, true>::GetPointer() const {
|
||||
assert(not this->Exhausted());
|
||||
return this->m_stack.top();
|
||||
}
|
||||
} //namespace implem
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
TreeIterator<T, N>::TreeIterator() {
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
TreeIterator<T, N>::TreeIterator (const TreeIterator& parOther) :
|
||||
parent_type(parOther)
|
||||
{
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
template <typename T1>
|
||||
TreeIterator<T, N>::TreeIterator (const TreeIterator<T1, N>& parOther) :
|
||||
parent_type(parOther)
|
||||
{
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
template <typename S>
|
||||
TreeIterator<T, N>::TreeIterator (S parCopyStackBottomUp, size_type parStackLen, size_type parMaxDepthHint) {
|
||||
assert(parStackLen > 0);
|
||||
this->m_stack.reserve(std::max(parStackLen, parMaxDepthHint));
|
||||
typename StackType::value_type prevNode = *parCopyStackBottomUp;
|
||||
++parCopyStackBottomUp;
|
||||
this->m_stack.push(prevNode);
|
||||
|
||||
for (size_type z = 1; z < parStackLen; ++z) {
|
||||
typename StackType::value_type currNode = *parCopyStackBottomUp;
|
||||
if (prevNode->left == currNode) {
|
||||
assert(this->m_stack.capacity() > this->m_stack.size());
|
||||
this->m_stack.push(currNode);
|
||||
}
|
||||
else {
|
||||
//If you get this assertion make sure the iterator you are
|
||||
//passing in is reversed (ie: from leaf to root)
|
||||
assert(currNode == prevNode->right);
|
||||
}
|
||||
|
||||
prevNode = currNode;
|
||||
++parCopyStackBottomUp;
|
||||
}
|
||||
assert(not this->Exhausted());
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
TreeIterator<T, N>::TreeIterator (NodeTypePointer parRoot, size_type parMaxDepthHint) {
|
||||
if (parMaxDepthHint > 0)
|
||||
this->m_stack.reserve(parMaxDepthHint);
|
||||
RecurseLeft(parRoot);
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
TreeIterator<T, N>::~TreeIterator() {
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///Post-increment
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
TreeIterator<T, N> TreeIterator<T, N>::operator++ (int) {
|
||||
assert(not this->Exhausted());
|
||||
TreeIterator<T, N> retVal = *this;
|
||||
++(*this);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///Pre-increment
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
TreeIterator<T, N>& TreeIterator<T, N>::operator++() {
|
||||
assert(not this->Exhausted());
|
||||
NodeTypePointer currNode = this->m_stack.top();
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
const size_type stackCapacity = this->m_stack.capacity();
|
||||
#endif
|
||||
this->m_stack.pop();
|
||||
#if defined(ASSERTIONSENABLED)
|
||||
//It shouldn't normally happen, but it's just to make sure
|
||||
assert(stackCapacity == this->m_stack.capacity());
|
||||
#endif
|
||||
RecurseLeft(currNode->right);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
const TreeIterator<T, N>& TreeIterator<T, N>::operator= (const TreeIterator& parOther) {
|
||||
this->m_stack = parOther.m_stack;
|
||||
assert(this->m_stack.capacity() >= parOther.m_stack.capacity());
|
||||
return *this;
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
bool TreeIterator<T, N>::operator== (const TreeIterator& parOther) const {
|
||||
return this->m_stack.size() == parOther.m_stack.size() and (this->m_stack.empty() or parOther.m_stack.top() == this->m_stack.top());
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
template <typename T, typename N>
|
||||
void TreeIterator<T, N>::RecurseLeft (NodeTypePointer parFrom) {
|
||||
NodeTypePointer currNode = parFrom;
|
||||
while (NULL != currNode) {
|
||||
assert(this->m_stack.capacity() > this->m_stack.size());
|
||||
this->m_stack.push(currNode);
|
||||
currNode = currNode->left;
|
||||
}
|
||||
}
|
||||
} //namespace dhandy
|
152
include/duckhandy/tree_iterator.hpp
Normal file
152
include/duckhandy/tree_iterator.hpp
Normal file
|
@ -0,0 +1,152 @@
|
|||
/* Copyright 2016-2024 Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* "duckhandy" is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef id6109D5EDE99D43C4909F084A231BF2C2
|
||||
#define id6109D5EDE99D43C4909F084A231BF2C2
|
||||
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <stack>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
namespace dhandy {
|
||||
namespace implem {
|
||||
template <typename P>
|
||||
class TreeIteratorStack : public std::stack<P, std::vector<P>> {
|
||||
public:
|
||||
void reserve (std::size_t size) {
|
||||
std::stack<P, std::vector<P>>::c.reserve(size);
|
||||
}
|
||||
|
||||
std::size_t capacity() const {
|
||||
return std::stack<P, std::vector<P>>::c.capacity();
|
||||
}
|
||||
private:
|
||||
};
|
||||
|
||||
template <typename P>
|
||||
class TreeIterator_base {
|
||||
template <typename P1> friend class TreeIterator_base;
|
||||
public:
|
||||
explicit TreeIterator_base ( void ) {}
|
||||
TreeIterator_base ( const TreeIterator_base& parOther );
|
||||
template <typename P1>
|
||||
explicit TreeIterator_base ( const TreeIterator_base<P1>& parOther );
|
||||
~TreeIterator_base ( void ) {}
|
||||
protected:
|
||||
typedef TreeIteratorStack<P> StackType;
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
bool Exhausted ( void ) const;
|
||||
StackType m_stack;
|
||||
};
|
||||
|
||||
template <typename T, typename N, bool Const>
|
||||
class TreeIterator_const_layer;
|
||||
template <typename T, typename N>
|
||||
class TreeIterator_const_layer<T, N, true> : protected TreeIterator_base<const N*> {
|
||||
template <typename T1, typename N1, bool Const1> friend class TreeIterator_const_layer;
|
||||
typedef TreeIterator_base<const N*> parent_type;
|
||||
public:
|
||||
typedef const T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef const T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef typename parent_type::size_type size_type;
|
||||
typedef typename parent_type::difference_type difference_type;
|
||||
typedef N NodeType;
|
||||
typedef const N* NodeTypePointer;
|
||||
enum { IS_CONST = 1 };
|
||||
TreeIterator_const_layer ( void ) {}
|
||||
TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {}
|
||||
template <typename T1, bool C1>
|
||||
explicit TreeIterator_const_layer ( const TreeIterator_const_layer<T1, N, C1>& parOther ) : parent_type(parOther) {}
|
||||
const_reference operator* ( void ) const;
|
||||
const_pointer operator-> ( void ) const;
|
||||
const N* GetPointer ( void ) const;
|
||||
protected:
|
||||
typedef typename parent_type::StackType StackType;
|
||||
};
|
||||
template <typename T, typename N>
|
||||
class TreeIterator_const_layer<T, N, false> : protected TreeIterator_base<N*> {
|
||||
template <typename T1, typename N1, bool Const1> friend class TreeIterator_const_layer;
|
||||
typedef TreeIterator_base<N*> parent_type;
|
||||
public:
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef typename parent_type::size_type size_type;
|
||||
typedef typename parent_type::difference_type difference_type;
|
||||
typedef N NodeType;
|
||||
typedef N* NodeTypePointer;
|
||||
enum { IS_CONST = 0 };
|
||||
TreeIterator_const_layer ( void ) {}
|
||||
TreeIterator_const_layer ( const TreeIterator_const_layer& parOther ) : parent_type(parOther) {}
|
||||
template <typename T1, bool C1>
|
||||
explicit TreeIterator_const_layer ( const TreeIterator_const_layer<T1, N, C1>& parOther ) : parent_type(parOther) {}
|
||||
reference operator* ( void );
|
||||
const_reference operator* ( void ) const;
|
||||
pointer operator-> ( void );
|
||||
const_pointer operator-> ( void ) const;
|
||||
const N* GetPointer ( void ) const;
|
||||
N* GetPointer ( void );
|
||||
protected:
|
||||
typedef typename parent_type::StackType StackType;
|
||||
};
|
||||
} //namespace implem
|
||||
|
||||
template <typename T, typename N>
|
||||
class TreeIterator : public implem::TreeIterator_const_layer<T, N, std::is_const<T>::value> {
|
||||
typedef implem::TreeIterator_const_layer<T, N, std::is_const<T>::value> parent_type;
|
||||
typedef typename parent_type::NodeTypePointer NodeTypePointer;
|
||||
typedef typename parent_type::NodeType NodeType;
|
||||
typedef typename parent_type::StackType StackType;
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef typename parent_type::difference_type difference_type;
|
||||
typedef typename parent_type::size_type size_type;
|
||||
typedef typename parent_type::pointer pointer;
|
||||
typedef typename parent_type::const_pointer const_pointer;
|
||||
typedef typename parent_type::reference reference;
|
||||
typedef typename parent_type::const_reference const_reference;
|
||||
|
||||
TreeIterator ( void );
|
||||
TreeIterator ( const TreeIterator& parOther );
|
||||
TreeIterator ( NodeTypePointer parRoot, size_type parMaxDepthHint );
|
||||
template <typename S>
|
||||
TreeIterator ( S parCopyStackBottomUp, size_type parStackLen, size_type parMaxDepthHint );
|
||||
template <typename T1>
|
||||
TreeIterator ( const TreeIterator<T1, N>& parOther );
|
||||
~TreeIterator ( void );
|
||||
|
||||
const TreeIterator& operator= ( const TreeIterator& parOther );
|
||||
bool operator== ( const TreeIterator& parOther ) const;
|
||||
bool operator!= ( const TreeIterator& parOther ) const { return not (*this == parOther); }
|
||||
TreeIterator& operator++ ( void ); //pre
|
||||
TreeIterator operator++ ( int ); //post
|
||||
|
||||
private:
|
||||
void RecurseLeft ( NodeTypePointer parFrom );
|
||||
};
|
||||
} //namespace dhandy
|
||||
|
||||
#include "implem/tree_iterator.inl"
|
||||
|
||||
#endif
|
|
@ -10,6 +10,7 @@ unit_test_prog = executable(meson.project_name(),
|
|||
'version_test.cpp',
|
||||
'tiger_test.cpp',
|
||||
'infix_iterator.cpp',
|
||||
'tree_iterator_test.cpp',
|
||||
install: false,
|
||||
dependencies: [sprout_dep, catch2_dep],
|
||||
include_directories: [public_incl],
|
||||
|
|
136
test/unit/tree_iterator_test.cpp
Normal file
136
test/unit/tree_iterator_test.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
/* Copyright 2016-2024 Michele Santullo
|
||||
* This file is part of "duckhandy".
|
||||
*
|
||||
* "duckhandy" is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* "duckhandy" is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with "duckhandy". If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "catch2/catch_test_macros.hpp"
|
||||
#include "duckhandy/tree_iterator.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
enum Letters : unsigned int {
|
||||
A = 'a', B, C, D, E, F, G, H, I
|
||||
};
|
||||
|
||||
struct TestNode {
|
||||
TestNode (unsigned int val) : content(val) {}
|
||||
TestNode* left{nullptr}, *right{nullptr};
|
||||
unsigned int content{0};
|
||||
};
|
||||
} //unnamed namespace
|
||||
|
||||
TEST_CASE("Check TreeIterator", "[TreeIterator][containers][iterator]") {
|
||||
typedef dhandy::TreeIterator<unsigned int, TestNode> TestIterator;
|
||||
|
||||
TestIterator empty;
|
||||
|
||||
{
|
||||
TestNode root{0xDEADBEEFu};
|
||||
TestIterator it{&root, 1};
|
||||
CHECK(*it == 0xDEADBEEFu);
|
||||
|
||||
++it;
|
||||
CHECK(it == empty);
|
||||
}
|
||||
|
||||
{
|
||||
TestNode root{A};
|
||||
TestNode l{B}, ll{C}, lr{D};
|
||||
TestNode r{E}, rl{F}, rr{G}, rll{H}, rrr{I};
|
||||
|
||||
root.left = &l;
|
||||
root.right = &r;
|
||||
l.left = ≪
|
||||
l.right = &lr;
|
||||
r.left = &rl;
|
||||
r.right = &rr;
|
||||
rl.left = &rll;
|
||||
rr.right = &rrr;
|
||||
|
||||
TestIterator it{&root, 4};
|
||||
CHECK(*it == C); //ll
|
||||
++it;
|
||||
CHECK(*it == B); //l
|
||||
it++;
|
||||
CHECK(*it == D); //lr
|
||||
it++;
|
||||
CHECK(*it == A); //root
|
||||
++it;
|
||||
CHECK(*it == H); //rll
|
||||
it++;
|
||||
CHECK(*it == F); //rl
|
||||
it++;
|
||||
CHECK(*it == E); //r
|
||||
++it;
|
||||
CHECK(*it == G); //rr
|
||||
++it;
|
||||
CHECK(*it == I); //rrr
|
||||
CHECK(it != empty);
|
||||
it++;
|
||||
CHECK(it == empty);
|
||||
}
|
||||
|
||||
{
|
||||
TestNode root{A};
|
||||
TestNode l{B}, ll{C}, lll{D}, llll{E}, lllll{F};
|
||||
root.left = &l;
|
||||
l.left = ≪
|
||||
ll.left = &lll;
|
||||
lll.left = &llll;
|
||||
llll.left = &lllll;
|
||||
|
||||
TestIterator it{&root, 6};
|
||||
CHECK(it != empty);
|
||||
CHECK(*it == F);
|
||||
++it;
|
||||
CHECK(*it == E);
|
||||
++it;
|
||||
CHECK(*it == D);
|
||||
++it;
|
||||
CHECK(*it == C);
|
||||
++it;
|
||||
CHECK(*it == B);
|
||||
++it;
|
||||
CHECK(*it == A);
|
||||
++it;
|
||||
CHECK(it == empty);
|
||||
}
|
||||
|
||||
{
|
||||
TestNode root{A};
|
||||
TestNode r{B}, rr{C}, rrr{D}, rrrr{E}, rrrrr{F};
|
||||
root.right = &r;
|
||||
r.right = &rr;
|
||||
rr.right = &rrr;
|
||||
rrr.right = &rrrr;
|
||||
rrrr.right = &rrrrr;
|
||||
|
||||
TestIterator it{&root, 6};
|
||||
CHECK(it != empty);
|
||||
CHECK(*it == A);
|
||||
++it;
|
||||
CHECK(*it == B);
|
||||
++it;
|
||||
CHECK(*it == C);
|
||||
++it;
|
||||
CHECK(*it == D);
|
||||
++it;
|
||||
CHECK(*it == E);
|
||||
++it;
|
||||
CHECK(*it == F);
|
||||
++it;
|
||||
CHECK(it == empty);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue