Say I have a struct of Items that I'm storing in an std::set and sorting like so:
struct Position
{
int x;
int y;
}
struct Item
{
std::string id;
Position position;
// NOTE: only `position` should matter for equality
operator==(const Item& other)
{
return position == position;
}
};
inline bool operator<(const Item& lhs, const Item& rhs)
{
if (lhs.position.x == rhs.position.x)
{
return lhs.position.y < rhs.position.y;
}
return lhs.position.x < rhs.position.x;
}
using ItemSet = std::set<Item>;
I want to use std::equal_range to search an ItemSet, except I want to search by Position. I know I could do something like:
ItemSet items;
Item tempItem;
tempItem.position = some_position;
auto result = std::equal_range(items.begin(), items.end(), tempItem);
But I would like to avoid the temporary Item.
I tried to use boost::transform_terator like so:
auto tr = [](const Item& item) { return item.pos; };
auto tr_begin = boost::make_transform_iterator(items.begin(), tr);
auto tr_end = boost::make_transform_iterator(items.end(), tr);
Position findme { 2, 1 };
auto result = std::equal_range(tr_begin, tr_end, findme);
But this doesn't compile for reasons I don't understand, and also even if it did work, how would I get an iterator into the original collection from result? Or maybe there's a better way overall to do this?
Here is a test harness show the problem: http://cpp.sh/3hzsq
Any help would be appreciated!
You can use std::set::find with a different type to avoid constructing an Item. Note that your set can only contain one item with a specific position.
You can either make Position directly comparable with Item (Add Item{} < Position{} and Position{} < Item{}) or create a new proxy class:
struct ItemPosition {
Position p;
};
inline bool operator<(const ItemPosition& l, const Item& r) {
return l.position.x == r.position.x ? l.position.y < r.position.y : l.position.x < r.position.x;
};
inline bool operator<(const Item& l, const ItemPosition& r) {
return l.position.x == r.position.x ? l.position.y < r.position.y : l.position.x < r.position.x;
};
// Change the comparator so it can compare with `ItemPosition` too
using ItemSet = std::set<Item, std::less<>>;
You can alternatively use a completely different comparator to make Position comparable with Item.
struct ItemComparator {
bool operator()(const Position& l, const Position& r) const {
return l.x == r.x ? l.y < r.y : l.x < r.x;
}
bool operator()(const Item& l, const Item& r) const {
return operator()(l.position, r.position);
}
bool operator()(const Item& l, const Position& r) const {
return operator()(l.position, r);
}
bool operator()(const Position& l, const Item& r) const {
return operator()(l, r.position);
}
using is_transparent = void;
};
using ItemSet = std::set<Item, ItemComparator>;
And use it like so:
Position findme { 2, 1 };
// Or just `items.find(findme)` if using a custom comparator
auto result = items.find(ItemPosition{ findme });
if (result == items.end()) {
// No item found
} else {
Item& item = *result;
// found item
}
Related
I'm testing std::set with a custom comparator. But I see the same object getting inserted twice.
Following is the object class:
class Info
{
public:
Info(string n, string oN, int dom):
name(n),
objName(oN),
domain(dom)
{}
void setName(std::string n) { name = n;}
void setObjName(std::string n) { objName = n;}
void setDomain(int dom) { domain = dom; }
std::string getName() const { return name;}
std::string getObjName() const { return objName;}
int getDomain() const { return domain;}
private:
std::string name;
std::string objName;
int domain;
};
Following is my custom comparator:
struct InfoCmp {
bool operator() (const Info &lhs, const Info &rhs) const {
if((lhs.getName() < rhs.getName()) || (lhs.getObjName() < rhs.getObjName()) || (lhs.getDomain() < rhs.getDomain()) ){
return true;
}
return false;
}
};
Following is the usage:
Info rst1("rst1", "rstObj1", 1);
Info rst2("rst2", "rstObj2", 2);
Info rst3("rst1", "rstObj3", 3);
std::set<Info,InfoCmp> resetSet;
resetSet.insert(rst1);
resetSet.insert(rst2);
resetSet.insert(rst3);
resetSet.insert(rst1);
resetSet.insert(rst2);
resetSet.insert(rst3);
I see rst2 inserted twice, but it shouldn't be as per my comparator.
I see that you've come up with your own solution, after recognizing from the comments that your original did not impose a strict object ordering as required by set. Here's a different version that only requires operator< and not operator==, making it consistent with the classes and algorithms of the standard library. It also simplifies things if you're e.g. doing a case insensitive comparison.
struct InfoCmp {
bool operator() (const Info &lhs, const Info &rhs) const {
if(lhs.getName() < rhs.getName())
return true;
if(rhs.getName() < lhs.getName())
return false;
if(lhs.getObjName() < rhs.getObjName())
return true;
if(rhs.getObjName() < lhs.getObjName())
return false;
return lhs.getDomain() < rhs.getDomain();
}
};
struct InfoCmp2 {
bool operator() (const Info &lhs, const Info &rhs) const {
return std::make_tuple(lhs.getName(), lhs.getObjName(), lhs.getDomain()) < std::make_tuple(rhs.getName(), rhs.getObjName(), rhs.getDomain());
}
};
This operator can written with make_tuple as well, and working fine.
as suggested by Cory Kramer, adding strict ordering in comparator fixed the problem.
struct InfoCmp {
bool operator() (const Info &lhs, const Info &rhs) const {
if((lhs.getName() < rhs.getName())
|| ( (lhs.getName() == rhs.getName()) && (lhs.getObjName() < rhs.getObjName()) )
|| ( (lhs.getName() == rhs.getName()) && (lhs.getObjName() == rhs.getObjName()) && (lhs.getDomain() < rhs.getDomain()) )){
return true;
}
return false;
}
};
I am trying to implement A* algorithm (with visualization in Qt). I've got this method:
result_path astar_algorithm::calculate(mapview* m_view)
{
map_view = m_view;
auto closed_set = std::vector<std::shared_ptr<node>>();
auto start_node = std::make_shared<node>(_start);
auto open_set = std::vector<std::shared_ptr<node>>{start_node};
std::map<node, node> came_from;
std::shared_ptr<node> current;
while (!open_set.empty())
{
current = *std::min_element(open_set.begin(), open_set.end());
if (*current == _end)
{
// TODO: Reconstruct a result path!!!
break;
}
open_set.erase(std::find(open_set.begin(), open_set.end(), current));
closed_set.push_back(current);
auto neighbors = get_neighbors(*current);
for (auto& neighbor : neighbors)
{
if (std::find_if(closed_set.begin(), closed_set.end(),
[&](std::shared_ptr<node> const& p) { return *p == neighbor; }) !=
closed_set.end())
continue;
auto tentative_g_score = current->G + 1;
if (std::find_if(open_set.begin(), open_set.end(), [&](std::shared_ptr<node> const& p) {
return *p == neighbor;
}) == open_set.end())
{
neighbor.G = tentative_g_score;
neighbor.H = heuristic_cost_estimate(neighbor.pos, _end);
neighbor.parent = current;
open_set.push_back(std::make_shared<node>(neighbor));
}
else if (tentative_g_score < neighbor.G)
{
neighbor.parent = current;
neighbor.G = tentative_g_score;
}
}
}
auto result = result_path();
while (*current != *start_node)
{
result.path.push_back(current->pos);
current = current->parent;
}
result.path.push_back(start_node.pos);
std::reverse(result.path.begin(), result.path.end());
return result;
}
It works, but I have a few problems:
if (std::find_if(closed_set.begin(), closed_set.end(),
[&](std::shared_ptr<node> const& p) { return *p == neighbor; }) !=
closed_set.end())
continue;
This line checks if a node is present in an std::vector and if so, it continues the loop (then there is a second line similar to this, it just checks if node is not actually present in the vector). I guess the better way would be to store those nodes in a vector and then searching and further adding would be easier (cuz I just have to check if the insert succeeded).
The problem is, afaik, to make this work I have to implement < operator. And so I did. I also made == and !=:
class node
{
public:
node() {}
node(const QPoint& p) : pos(p) {}
bool operator == (const node& o ) const { return pos == o.pos; }
bool operator == (const QPoint& o ) const { return pos == o; }
bool operator != (const node& o) const {return pos != o.pos; }
bool operator <(const node& o ) const { return G + H < o.G + o.H; }
QPoint pos;
std::shared_ptr<node> parent;
int G = 0;
int H = 0;
};
It works perfectly for the earlier search for std::min_element (it searches for a node with the lowest F value (F=G+H)), it uses < operator. But then I tried to use a set, so those two vectors at the beginning of the method were set and when I wanted to just insert or even check if a node is already in a set and then insert I had a problem. Many of those nodes will have the same G+H value, as the maze which I used was kind of simple (i.e. a maze completely without terrains). I checked it under the debugger and the nodes with unique .pos values (QPoint) were not added to the set just like they weren't unique (but if the node had a different G+H value than any node in the set, it would be added). For the vector the same nodes of course work, cuz there are no checks made, I checked everything carefully under the debugger.
I don't know if I am getting this wrong, but I thought it would use a == or != operators but as seen in this answer: link, it actually uses < operator, which in my case would not distinguish between two nodes (cuz the unique part of each node is its position in the grid (node represents a box in a grid, which can represent a maze or smth similar))
So, is there something I am doing wrong or am I actually getting this right, and the inserting (which checks if the element is unique) or checking if the element exists in a set uses < operator and I cannot do anything about it? (cuz I would like to have my < operator with comparing G+H and then I would like the searching/inserting to use the == operator to compare)
This is the example that I wrote (I forgot I have Microsoft C++ Compiler from the command line - cl.exe)
#include <algorithm>
#include <iostream>
#include <memory>
#include <set>
class Point
{
public:
int _x, _y;
Point() : _x(0), _y(0) {}
Point(int x, int y) : _x(x), _y(y) {}
bool operator==(const Point& p) const { return _x == p._x && _y == p._y; }
bool operator!=(const Point& p) const { return _x != p._x && _y != p._y; }
};
class node
{
public:
node() {}
node(const Point& p) : pos(p) {}
bool operator==(const node& o) const { return pos == o.pos; }
bool operator==(const Point& o) const { return pos == o; }
bool operator!=(const node& o) const { return pos != o.pos; }
bool operator<(const node& o) const { return G + H < o.G + o.H; }
Point pos;
std::shared_ptr<node> parent;
int G = 0;
int H = 0;
};
int main()
{
node n1(Point(0, 0));
n1.G = 1;
n1.H = 1;
node n2(Point(1, 1));
n2.G = 2;
n2.H = 2;
node n3(Point(2, 2));
n3.G = 1;
n3.H = 1;
std::set<node> nodes;
nodes.insert(n1);
nodes.insert(n2);
nodes.insert(n3);
auto min = (*std::min_element(nodes.begin(), nodes.end())).pos;
std::cout << min._x << " " << min._y << '\n';
std::cout << nodes.size() << '\n';
}
>main.exe
0 0
2
std::min_element works, but those are 3 unique nodes for me (differet .pos values) so there should be 3 nodes in the set. And that's what I want to achieve
I thought it would use a == or != operators
No, std::set does not use operators == and !=,
std::set uses just one function, the comparison function (the second template argument, which defaults to std::less<T>).
Uniqueness is based on the equivalence relation which is derived from applying the same comparison function twice: !a<b && !b<a.
It seems you don't really need uniqueness, in which case you can use std::multiset instead. It will maintain the order, but will not enforce uniqueness.
std::set<node> nodes;
. . .
auto min = (*std::min_element(nodes.begin(), nodes.end())).pos;
std::min_element is always O(N). Using it on a set defeats the purpose of having a set.
Just get the first element, which will be the smallest (according to the comparison function).
auto min = begin(nodes)->pos;
i have to filter a container and the copy of each item is expensive. So i came up with this C++ code .. maybe there is better concept that i miss. Please comment. Also important that operations like counting and empty are also fast.
The sample below will create a vector with some items and return a filtered copy and doing some boolean operations.
#include <vector>
#include <functional>
template <class X> struct filterChainT {
/// the list here
const X & list;
/// take store type from access operator
typedef decltype(list[0]) storeType;
/// the test functions
std::function<bool(storeType &) > tests[10];
/// counting the test (don´t use array here)
size_t countTest;
/// ctor with given list
filterChainT(const X & list):list(list),countTest(0) { }
/// add a rule here
filterChainT<X> & apply(const std::function<bool(storeType &) > & fnc)
{
tests[countTest++] = fnc;
return *this;
}
/// downcast to container (will return the filter copy)
operator X() const
{
X ret;
eval([&](const storeType & hit) { ret.push_back(hit); return false; });
return ret;
}
/// just count item after filter
int count() const
{
int count = 0;
eval([&](const storeType hit) { count++; return false; });
return count;
}
bool operator==(int number) const { return count() == number; }
bool operator>(int number) const
{
int count = 0;
return eval([&](const storeType & hit) { return ++count>number; });
}
bool operator<(int number) const
{
int count = 0;
return !eval([&](const storeType & hit) { return ++count>=number; });
}
//// the magic eval functions. Return true if the fnc object abort the loop
template <class FNC> bool eval(const FNC fnc) const
{
for (auto i : list)
{
for (size_t t = 0; t < countTest; t++)
{
if (!tests[t](i))
goto next;
}
if (fnc(i))
return true;
next:;
}
return false;
}
};
struct myFilter : public filterChainT < std::vector<int>> {
myFilter(const std::vector<int> & in) :filterChainT<std::vector<int>>(in){ };
// filter items i%2==0
myFilter & mod()
{
apply([](const int & i) { return i % 2; });
return *this;
}
// filter items smaller than x
myFilter & smaller(int x)
{
apply([=](const int & i) { return i<x; });
return *this;
}
};
int main()
{
std::vector<int> vec;
vec.push_back(1);
vec.push_back(3);
vec.push_back(10);
// apply filter and return result use two filters „mod“ and „smaller“
std::vector<int> ret = myFilter(vec).mod().smaller(5);
// just see if they are less then 2 items in list same filter than above
bool res1 = myFilter(vec).mod().smaller(5) < 2;
// some custom without the helper -> filter all items larger than 3 and put in list
std::vector<int> result=filterChainT < std::vector<int>>(vec).apply([](const int & p) { return p > 3; });
}
regards
Markus
the hint with "expression templates" works very well. Two times faster than my posting. Now the code looks like this. Thank you very much for pointing to the right place.
I use the same concept as the WIKI entry by adding a plus operation to create the filter chain and a final function to reduce the given list with this filter.
template <class T> struct filterNodeBaseT {
template <class X> bool apply(const X& x) const { return static_cast<T const & >(*this).apply(x); }
template <class LST> LST filter(const LST & input) const
{ LST ret;
for (auto i : input)
{ if (this->apply(i))
ret.push_back(i);
}
return ret;
}
template <class LST> int count(const LST & input) const
{ int ret = 0;
for (auto i : input)
{ if (this->apply(i))
ret++;
}
return ret;
}
};
template <class T1, class T2> struct filterCombine : public filterNodeBaseT<filterCombine<T1, T2> > {
const T1 & t1;
const T2 & t2;
filterCombine(const T1 & t1, const T2 & t2) :t1(t1), t2(t2) { }
template <class X> bool apply(const X & x) const { return t1.apply(x) && t2.apply(x); }
};
template <class T1,class T2> filterCombine<T1,T2> operator + (const T1 & t1,const T2 & t2)
{ return filterCombine<T1,T2>(t1,t2); }
struct filterNodeSmaller : public filterNodeBaseT<filterNodeSmaller> {
int limit;
filterNodeSmaller(int limit) :limit(limit) {};
bool apply(const int & x) const { return x < limit; }
};
struct filterNodeLarger: public filterNodeBaseT<filterNodeLarger> {
int limit;
filterNodeLarger(int limit) :limit(limit) {};
bool apply(const int & x) const { return x > limit; }
};
struct filterNodeMod : public filterNodeBaseT<filterNodeMod> {
bool apply(const int & x) const { return x % 2; }
};
struct filterStrlenLarger : public filterNodeBaseT<filterStrlenLarger> {
int limit;
filterStrlenLarger(int limit) :limit(limit) { };
bool apply(const std::string & s) const { return s.length() > limit; }
};
struct filterStrGreater : public filterNodeBaseT<filterStrGreater> {
std::string cmp;
filterStrGreater(const std::string & cmp) :cmp(cmp) { };
bool apply(const std::string & s) const { return s>cmp; }
};
_declspec(noinline) void nodeTest()
{
std::vector<int> intList;
intList.push_back(1); intList.push_back(3); intList.push_back(4);
int count= (filterNodeMod() + filterNodeSmaller(5)+ filterNodeLarger(1)).count(intList);
std::vector<int> resList1= (filterNodeMod() + filterNodeSmaller(5)+filterNodeLarger(1)).filter(intList);
printf("%d\n", count);
std::vector<std::string> strList;
strList.push_back("Hello");
strList.push_back("World");
strList.push_back("!");
count = (filterStrlenLarger(3)+filterStrGreater("Hello")).count(strList);
std::vector<std::string> resList2= (filterStrlenLarger(3) + filterStrGreater("Hello")).filter(strList);
printf("%d\n", count);
}
I need to know how to overload the operator = != and < so I could work with set<set<object> >
I have my class:
class pr{
private:
set<set<e> > pr_;
public:
pr();
~pr();
void set_pr(set<e> a);
pr& operator=(const pr& a) const;
bool operator!=(const pr& a) const;
bool operator<(const pr& a) const;
};
So if I have a set like this: {{1,2,3},{4,5}} where the numbers are objects.
I would like to do operations with the sets in other class like this:
void otherclass::myfunction(){
pr prt; //I create the objects
pr prt_old;
set<e> C1; //I create the subset and fill
set<e> C2;
//C1 and C2 filled here
prt.set_pr(C1); //Insert the set<e> into set<set<e>>
prt.set_pr(C2); //It will fail because i dont know how to compare set<e> < <set<e>
while(prt != prt_old){
prt_old = prt ;
prt = create(prt_old);
}
//...
I tried to overload doing this:
pr& pr::operator=(const pr& a) const{
this->clear();
for(set<set<e> >::iterator it =a.begin();it!=a.end();it++){
for(set<e>::iterator j = it->begin(); j != it->end();j++){
this->set_pr(*j);
}
}
return *this;
}
bool pr::operator!=(const pr& a) const{
if(this->size() != a.size()){
return 1;
}
//Now i don't know how to continue for check if for example
// i had {{1,2},{3,4}} and {{1},{2}}
//this two set have same size but they are differnt
//How could i just iterate through the two sets at same time
// and check if subset have too same size or if the objects inside the subset are equal
//Also i need the operator < to insert a set<e> into a set<set<e> > but how??
//Note: class 'e' has already defined the "operator<" for when I insert objects in the set<e>
//And i order them by a function that return an integrer
To test if one set is contained in the other, you iterate over each member of the first set, and test if it exists in the second set.
bool operator<(const pr& a) const {
for (auto _set : _data) {
if (a._data.find(_set) == a._data.end())
return false;
}
return true;
}
To test if two sets are identical, you test their size is equal, and that one is contained in the other
bool operator==(const pr& a) const {
return _data.size() == a._data.size() && *this < a;
}
But notice that there is no need to define an operator==, because the default one defined by std::set is fine.
Here is a full functioning program:
#include <iostream>
#include <set>
using namespace std;
template <class e>
class pr {
private:
set<set<e> > _data;
public:
void insert(set<e> a) { _data.insert(a); }
bool operator==(const pr& a) const {
return _data.size() == a._data.size() && *this < a;
}
bool operator!=(const pr& a) const { return !(*this == a); }
bool operator<(const pr& a) const {
for (auto _set : _data) {
if (a._data.find(_set) == a._data.end())
return false;
}
return true;
}
};
int main()
{
pr<int> a,b,c;
a.insert(set<int>({ 1 }));
b.insert(set<int>({ 1 }));
b.insert(set<int>({ 1, 2 }));
c.insert(set<int>({ 1, 2 }));
c.insert(set<int>({ 1 }));
std::cout << ((a<b) ? "a<b\n" : "NOT a<b\n");
std::cout << ((b<a) ? "b<a\n" : "NOT b<a\n");
std::cout << ((a==c) ? "a==c\n" : "NOT a==c\n");
std::cout << ((b==c) ? "b==c\n" : "NOT b==c\n");
std::cout << ((a==b) ? "a==b\n" : "NOT a==b\n");
return 0;
}
I'm trying to implement a container in C++ that uses a flat array to store the data but iterates over that data in pairs. Now I could easily change the implementation such that the container holds a vector of std::pair however I want to iterate through pairs starting at element 0 or at element 1.
To illustrate what I want to achieve, if my underlying array looks like:
1,2,3,4,5,6,7,8
I want to define two iterators, one which returns the pairs:
(1,2), (3,4), (5,6), (7,8)
and the second iterator to return the pairs:
(2,3), (4,5), (6,7)
is this possible to do while still allowing the elements of the iterator to be references of the underlying array?
It is possible to write your own iterator, which iterates over the elements. The following question shows some explanations on how that is done:
Custom Iterator in C++.
You can then return the desired values as std::pair and iterate to the next element-pair (by incrementing the counter by 2).
Boost library has got Iterator Adaptor that allows you to wrap other iterator types and change or adapt their functionality. Here's how you could use it for your purpose:
#include <boost/iterator/iterator_adaptor.hpp>
#include <vector>
struct iterator :
public boost::iterator_adaptor<
iterator, // the name of our class, see docs for details
std::vector<int>::iterator, // underlying base iterator
std::pair<int&, int&>, // our value type
boost::forward_traversal_tag // the category you wish to give it
>
{
// need this to convert from vector::iterator to ours
explicit iterator(std::vector<int>::iterator i)
: iterator::iterator_adaptor_(i) {}
value_type operator*()
{
return value_type(
*base_reference(),
*(base_reference()+1)
);
}
};
Example of usage:
std::vector<int> v {1,2,3,4};
iterator it(v.begin());
++it;
(*it).first = 0; // TODO: operator->
(*it).second = 0;
for (int i : v) std::cout << i << ' '; // prints 1 0 0 4
You'll also need to override comparison to properly handle end condition, etc. Hope that helps.
Just thought I'd put in what I actually used in my code. I didn't want to use boost as suggested by #jrok but the type std::pair<int&, int&> in their answer gave me a hint of what was required.
Below is the class that I constructed which uses two iterators. A RepeatIterator that returns pairs starting on even indexes in the underlying data, and a SpacerIterator that returns pairs starting on odd indexes.
class RepeatArray {
typedef std::vector<int> storage_t;
public:
class RepeatIterator {
public:
typedef RepeatIterator self_t;
typedef int value_t;
typedef int& reference_t;
typedef int* pointer_t;
typedef std::pair<reference_t, reference_t> return_t;
RepeatIterator(storage_t::iterator input) : current_pos(input){}
return_t operator *() {
return return_t(*(current_pos), *(current_pos + 1 ));
}
self_t operator++() { self_t i = *this; current_pos += 2; return i; }
self_t operator++(int junk) { current_pos+=2; return *this; }
bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }
private:
storage_t::iterator current_pos;
};
class SpacerIterator {
public:
typedef SpacerIterator self_t;
typedef int value_t;
typedef int& reference_t;
typedef int* pointer_t;
typedef std::pair<reference_t, reference_t> return_t;
SpacerIterator(storage_t::iterator input) : current_pos(input){}
return_t operator *() {
return return_t(*(current_pos), *(current_pos + 1 ));
}
self_t operator++() { self_t i = *this; current_pos += 2; return i; }
self_t operator++(int junk) { current_pos+=2; return *this; }
bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }
private:
storage_t::iterator current_pos;
};
void add(int start, int end) {
positions.push_back(start);
positions.push_back(end);
}
void dump() {
for (auto i : positions) {
std::cout <<i<<",";
}
std::cout <<std::endl;
}
RepeatIterator repeatBegin(){return RepeatIterator(positions.begin());}
RepeatIterator repeatEnd(){return RepeatIterator(positions.end());}
SpacerIterator spacerBegin(){return SpacerIterator(positions.begin() + 1);}
SpacerIterator spacerEnd(){return SpacerIterator(positions.end() - 1);}
protected:
storage_t positions;
};
And then the tesing program compiled using clang++ -std=c++0x -o testRepeatArray RepeatArray.cpp
int main() {
RepeatArray r = RepeatArray();
r.add(1,3);
r.add(7,12);
std::cout<<"original:"<<std::endl;
r.dump();
std::cout << "Testing Repeat iterator:"<<std::endl;
for (RepeatArray::RepeatIterator it2 = r.repeatBegin(); it2 != r.repeatEnd(); ++it2) {
std::cout << (*it2).first <<","<< (*it2).second << std::endl;
}
std::cout << "Testing Spacer iterator:"<<std::endl;
for (RepeatArray::SpacerIterator it3 = r.spacerBegin(); it3 != r.spacerEnd(); ++it3) {
std::cout << (*it3).first <<","<< (*it3).second << std::endl;
}
std::cout<<"Testing modification:"<<std::endl;
RepeatArray::RepeatIterator it = r.repeatBegin();
(*it).first = 0;
(*it).second = 123;
r.dump();
return 0;
}