#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <deque>
#include <vector>
using std::begin;
using std::end;
class NameCollection
{
public:
typedef std::vector<std::pair<bool, std::string>> container_type;
// This is an ad hoc attempt at an iterator proxy; I wouldn't take the
// iterator stuff too seriously as any sort of example code.
struct const_iterator
{
const_iterator(container_type::const_iterator it) : _iterator(it) {}
std::string operator->() const { return _iterator->second;}
std::string operator*() const { return _iterator->second;}
const_iterator& operator++() { ++_iterator; return *this;}
const_iterator operator++(int) { const_iterator result(*this); ++_iterator; return result; }
bool operator==(const const_iterator& it) const { return _iterator == it._iterator;}
bool operator!=(const const_iterator& it) const { return !(*this == it);}
operator container_type::const_iterator() { return _iterator; }
private:
container_type::const_iterator _iterator;
};
friend NameCollection::const_iterator begin(const NameCollection&);
friend NameCollection::const_iterator end(const NameCollection&);
std::vector<std::string> getSelected() const;
unsigned size() const {return _names.size();}
void add(const std::string& s);
void select(const std::string& s);
bool selected(const std::string& s) const;
void eraseSelected();
std::string operator [](unsigned index) const { return _names[index].second ; }
private:
container_type::iterator _find(const std::string& s) const
{
container_type & names = const_cast<container_type&>(_names); // compiler barfs if const_iterators are used. TODO: Research.
return std::find_if(begin(names), end(names), [&](const container_type::value_type& value) { return value.second == s; });
}
container_type _names;
};
std::vector<std::string> NameCollection::getSelected() const
{
std::vector<std::string> selected;
for (auto & name : _names)
if (name.first)
selected.push_back(name.second);
return selected;
}
void NameCollection::add(const std::string& s)
{
if (_find(s) == end(_names))
_names.emplace_back(false, s);
}
void NameCollection::select(const std::string& s)
{
auto it = _find(s);
if (it != end(_names))
it->first = true;
}
bool NameCollection::selected(const std::string& s) const
{
auto it = _find(s);
return it == end(_names) ? false : it->first;
}
void NameCollection::eraseSelected()
{
auto it = begin(_names);
while (it != end(_names))
{
if (it->first)
it = _names.erase(it);
else
++it;
}
}
NameCollection::const_iterator begin(const NameCollection& coll)
{
return begin(coll._names);
}
NameCollection::const_iterator end(const NameCollection& coll)
{
return end(coll._names);
}
void print(const NameCollection& nc, std::ostream& os = std::cout)
{
for (const auto name : nc)
std::cout << std::setw(2) << (nc.selected(name) ? "*" : "") << ' ' << name << '\n';
}
int main()
{
NameCollection coll;
for (char i = 'a'; i <= 'd'; ++i)
{
for (char j = 'a'; j <= 'd'; ++j)
coll.add(std::string(1, i) + j);
}
std::cout << "Original:\n";
print(coll);
for (unsigned i = 0; i < coll.size(); i += 3)
coll.select(coll[i]);
std::cout << "\nAfter selection:\n";
print(coll);
coll.eraseSelected();
std::cout << "\nAfter erase:\n";
print(coll);
}