How to adapt a visitor interface to an iterator interface? - c++

I'm wondering whether there is a good design pattern or idiom to realize the following:
You have an existing class that provides only a visitor interface, as follows
class Visitor {
public:
virtual ~Visitor() { }
virtual void visit(Node *n) = 0;
};
class Tree {
public:
void accept(Visitor *v);
};
And you want to have an interface that can be used as follows, which should iterate through the tree in the same order that the visitor would have its visit function called.
for(iterator it(...), ite(...); it != ite; ++it) {
/* process node */
}
The problem appears to be that when we just call visit, we are out of control, and can't temporarily "go back" to the loop body to execute the action for one node. This looks like it should occur regularly in real world programs. Any idea how to solve it?

In the general case, I don't think it's possible, at least not cleanly.
At least as it's usually defined, an iterator expects to deal with a homogeneous collection. I.e., an iterator is normally defined something like:
template <class Element>
class iterator // ...
...so a specific iterator can only work with elements of one specific type. The most you can do to work with differing types is create an iterator to (a pointer/reference to) a base class, and let it deal with objects of derived classes.
By contrast, it's pretty easy to write a visitor like this:
class MyVisitor {
public:
void VisitOneType(OneType const *element);
void VisitAnotherType(AnotherType const *element);
};
This can visit nodes of either OneType or AnotherType, even if the two are completely unrelated. Basically, you have one Visit member function in your Visitor class for every different type of class that it will be able to visit.
Looked at from a slightly different direction, an iterator is basically a specialized form of visitor that only works for one type of object. You exchange a little more control over the visitation pattern in exchange for losing the ability to visit unrelated types of objects.
If you only need to deal with one type (though that one type may be a base class, and the visited objects are of various derived types), then the obvious method would be to build a "bridge" class that visits objects (Tree nodes, in your example), and when its visit is called, it just copies the address of the node it's visiting into some collection that supports iterators:
template <class T>
class Bridge {
std::vector<T *> nodes;
public:
virtual void visit(T *n) {
nodes.push_back(n);
}
typedef std::vector<T *>::iterator iterator;
iterator begin() { return nodes.begin(); }
iterator end() { return nodes.end(); }
};
Using this would be a two-step process: first visit the nodes like a visitor normally would, then having collected together the nodes of interest you can iterate through them just like you would any other collection that provides iterators. At that point, your visitation pattern is limited only by the class of iterator provided by the collection you use in your bridge.

I had this problem in a real-world setting with an R-tree implementation that provided a visitor interface, whereas I needed an iterator interface. The suggestion by Jerry above works only if you can accept storing all the results in a collection. That may result in high memory consumption if your result set is huge and you don't really need to store them.
One solution that will work for sure is to launch the visitor in a separate thread and start waiting on a conditional variable for the results. When a visit call is made, you store the current result into a shared temp location, and use another conditional variable to wait for the next request. You signal the caller (main) thread's conditional variable before you wait on your own. The caller, which is implementing the iterator interface can then return the value stored at the temp location. During the next iteration, it could signal the visitor thread's conditional variable, and wait on its own for the next item. Unfortunately, this is somewhat costly if you do it on a per-item basis. You can buffer some items to improve the performance.
What we really need is an extra stack and to alternate between two contexts. This abstraction is provided by coroutines. In C++, boost::coroutine provides a clean implementation. Below I include a full example of how visitor pattern can be adapted into an iterator pattern.
#include <iostream>
#include <boost/bind.hpp>
#include <boost/coroutine/coroutine.hpp>
template<typename Data>
class Visitor
{
public:
virtual ~Visitor() { }
virtual bool visit(Data const & data) = 0;
};
template <typename Data>
class Visitable
{
public:
virtual ~Visitable() {}
virtual void performVisits(Visitor<Data> & visitor) = 0;
};
// Assume we cannot change the code that appears above
template<typename Data>
class VisitableIterator : public Visitor<Data>
{
private:
typedef boost::coroutines::coroutine<void()> coro_t;
public:
VisitableIterator(Visitable<Data> & visitable)
: valid_(true), visitable_(visitable)
{
coro_ = coro_t(boost::bind(&VisitableIterator::visitCoro, this, _1));
}
bool isValid() const
{
return valid_;
}
Data const & getData() const
{
return *data_;
}
void moveToNext()
{
if(valid_)
coro_();
}
private:
void visitCoro(coro_t::caller_type & ca)
{
ca_ = & ca;
visitable_.performVisits(*static_cast<Visitor<Data> *>(this));
valid_ = false;
}
bool visit(Data const & data)
{
data_ = &data;
(*ca_)();
return false;
}
private:
bool valid_;
Data const * data_;
coro_t coro_;
coro_t::caller_type * ca_;
Visitable<Data> & visitable_;
};
// Example use below
class Counter : public Visitable<int>
{
public:
Counter(int start, int end)
: start_(start), end_(end) {}
void performVisits(Visitor<int> & visitor)
{
bool terminated = false;
for (int current=start_; !terminated && current<=end_; ++current)
terminated = visitor.visit(current);
}
private:
int start_;
int end_;
};
class CounterVisitor : public Visitor<int>
{
public:
bool visit(int const & data)
{
std::cerr << data << std::endl;
return false; // not terminated
}
};
int main(void)
{
{ // using a visitor
Counter counter(1, 100);
CounterVisitor visitor;
counter.performVisits(visitor);
}
{ // using an iterator
Counter counter(1, 100);
VisitableIterator<int> iter(static_cast<Visitable<int>&>(counter));
for (; iter.isValid(); iter.moveToNext()) {
int data = iter.getData();
std::cerr << data << std::endl;
}
}
return EXIT_SUCCESS;
}

Building traversal logic in the visitors implementations is indeed not flexible. A usable way to cleanly separate traversing composite structures from visitation may be done via visitor combinators (there are other papers, feel free to google for them).
These slides about the same topic may also be of interest. They explain how to get clean syntax à la boost::spirit rules.

Related

Using std::unique_ptr of a polymorphic class as key in std::unordered_map

My problem comes from a project that I'm supposed to finish. I have to create an std::unordered_map<T, unsigned int> where T is a pointer to a base, polymorphic class. After a while, I figured that it will also be a good practice to use an std::unique_ptr<T> as a key, since my map is meant to own the objects. Let me introduce some backstory:
Consider class hierarchy with polymorphic sell_obj as a base class. book and table inheriting from that class. We now know that we need to create a std::unordered_map<std::unique_ptr<sell_obj*>, unsigned int>. Therefore, erasing a pair from that map will automatically free the memory pointed by key. The whole idea is to have keys pointing to books/tables and value of those keys will represent the amount of that product that our shop contains.
As we are dealing with std::unordered_map, we should specify hashes for all three classes. To simplify things, I specified them in main like this:
namespace std{
template <> struct hash<book>{
size_t operator()(const book& b) const
{
return 1; // simplified
}
};
template <> struct hash<table>{
size_t operator()(const table& b) const
{
return 2; // simplified
}
};
// The standard provides a specilization so that std::hash<unique_ptr<T>> is the same as std::hash<T*>.
template <> struct hash<sell_obj*>{
size_t operator()(const sell_obj *s) const
{
const book *b_p = dynamic_cast<const book*>(s);
if(b_p != nullptr) return std::hash<book>()(*b_p);
else{
const table *t_p = static_cast<const table*>(s);
return std::hash<table>()(*t_p);
}
}
};
}
Now let's look at implementation of the map. We have a class called Shop which looks like this:
#include "sell_obj.h"
#include "book.h"
#include "table.h"
#include <unordered_map>
#include <memory>
class Shop
{
public:
Shop();
void add_sell_obj(sell_obj&);
void remove_sell_obj(sell_obj&);
private:
std::unordered_map<std::unique_ptr<sell_obj>, unsigned int> storeroom;
};
and implementation of two, crucial functions:
void Shop::add_sell_obj(sell_obj& s_o)
{
std::unique_ptr<sell_obj> n_ptr(&s_o);
storeroom[std::move(n_ptr)]++;
}
void Shop::remove_sell_obj(sell_obj& s_o)
{
std::unique_ptr<sell_obj> n_ptr(&s_o);
auto target = storeroom.find(std::move(n_ptr));
if(target != storeroom.end() && target->second > 0) target->second--;
}
in my main I try to run the following code:
int main()
{
book *b1 = new book("foo", "bar", 10);
sell_obj *ptr = b1;
Shop S_H;
S_H.add_sell_obj(*ptr); // works fine I guess
S_H.remove_sell_obj(*ptr); // usually (not always) crashes [SIGSEGV]
return 0;
}
my question is - where does my logic fail? I heard that it's fine to use std::unique_ptr in STL containters since C++11. What's causing the crash? Debugger does not provide any information besides the crash occurance.
If more information about the project will be needed, please point it out. Thank you for reading
There are quite a few problems with logic in the question. First of all:
Consider class hierarchy with polymorphic sell_obj as base class. book and table inheriting from that class. We now know that we need to create a std::unordered_map<std::unique_ptr<sell_obj*>, unsigned int>.
In such cases std::unique_ptr<sell_obj*> is not what we would want. We would want std::unique_ptr<sell_obj>. Without the *. std::unique_ptr is already "a pointer".
As we are dealing with std::unordered_map, we should specify hashes for all three classes. To simplify things, I specified them in main like this: [...]
This is also quite of an undesired approach. This would require changing that part of the code every time we add another subclass in the hierarchy. It would be best to delegate the hashing (and comparing) polymorphically to avoid such problems, exactly as #1201programalarm suggested.
[...] implementation of two, crucial functions:
void Shop::add_sell_obj(sell_obj& s_o)
{
std::unique_ptr<sell_obj> n_ptr(&s_o);
storeroom[std::move(n_ptr)]++;
}
void Shop::remove_sell_obj(sell_obj& s_o)
{
std::unique_ptr<sell_obj> n_ptr(&s_o);
auto target = storeroom.find(std::move(n_ptr));
if(target != storeroom.end() && target->second > 0) target->second--;
}
This is wrong for couple of reasons. First of all, taking an argument by non-const reference suggest modification of the object. Second of all, the creation of n_ptr from a pointer obtained by using & on an argumnet is incredibly risky. It assumes that the object is allocated on the heap and it is unowned. A situation that generally should not take place and is incredibly dangerous. In case where the passed object is on the stack and / or is already managed by some other owner, this is a recipe for a disaster (like a segfault).
What's more, it is more or less guaranteed to end up in a disaster, since both add_sell_obj() and remove_sell_obj() create std::unique_ptrs to potentially the same object. This is exactly the case from the original question's main(). Two std::unique_ptrs pointing to the same object result in double delete.
While it's not necessarily the best approach for this problem if one uses C++ (as compared to Java), there are couple of interesting tools that can be used for this task. The code below assumes C++20.
The class hierarchy
First of all, we need a base class that will be used when referring to all the objects stored in the shop:
struct sell_object { };
And then we need to introduce classes that will represent conrete objects:
class book : public sell_object {
std::string title;
public:
book(std::string title) : title(std::move(title)) { }
};
class table : public sell_object {
int number_of_legs = 0;
public:
table(int number_of_legs) : number_of_legs(number_of_legs) { }
};
For simplicity (but to still have some distinctions) I chose for them to have just one, distinct field (title and number_of_legs).
The storage
The shop class that will represent storage for any sell_object needs to somehow store, well, any sell_object. For that we either need to use pointers or references to the base class. You can't have a container of references, so it's best to use pointers. Smart pointers.
Originally the question suggested the usage of std::unordered_map. Let us stick with it:
class shop {
std::unordered_map<
std::unique_ptr<sell_object>, int,
> storage;
public:
auto add(...) -> void {
...
}
auto remove(...) -> void {
...
}
};
It is worth mentioning that we chose std::unique_ptr as key for our map. That means that the storage is going to copy the passed objects and use the copies it owns to compare with elements we query (add or remove). No more than one equal object will be copied, though.
The fixed version of storage
There is a problem, however. std::unordered_map uses hashing and we need to provide a hash strategy for std::unique_ptr<sell_object>. Well, there already is one and it uses the hash strategy for T*. The problem is that we want to have custom hashing. Those particular std::unique_ptr<sell_object>s should be hashed according to the associated sell_objects.
Because of this, I opt to choose a different approach than the one proposed in the question. Instead of providing a global specialization in the std namespace, I will choose a custom hashing object and a custom comparator:
class shop {
struct sell_object_hash {
auto operator()(std::unique_ptr<sell_object> const& object) const -> std::size_t {
return object->hash();
}
};
struct sell_object_equal {
auto operator()(
std::unique_ptr<sell_object> const& lhs,
std::unique_ptr<sell_object> const& rhs
) const -> bool {
return (*lhs <=> *rhs) == 0;
}
};
std::unordered_map<
std::unique_ptr<sell_object>, int,
sell_object_hash, sell_object_equal
> storage;
public:
auto add(...) -> void {
...
}
auto remove(...) -> void {
...
}
};
Notice a few things. First of all, the type of storage has changed. No longer it is an std::unordered_map<std::unique_ptr<T>, int>, but an std::unordered_map<std::unique_ptr<T>, int, sell_object_hash, sell_object_equal>. This is to indicate that we are using custom hasher (sell_object_hash) and custom comparator (sell_object_equal).
The lines we need to pay extra attention are:
return object->hash();
return (*lhs <=> *rhs) == 0;
Onto them:
return object->hash();
This is a delegation of hashing. Instead of being an observer and trying to have a type that for each and every possible type derived from sell_object implements a different hashing, we require that those objects supply the sufficient hashing themselves. In the original question, the std::hash specialization was the said "observer". It certainly did not scale as a solution.
In order to achieve the aforementioned, we modify the base class to impose the listed requirement:
struct sell_object {
virtual auto hash() const -> std::size_t = 0;
};
Thus we also need to change our book and table classes:
class book : public sell_object {
std::string title;
public:
book(std::string title) : title(std::move(title)) { }
auto hash() const -> std::size_t override {
return std::hash<std::string>()(title);
}
};
class table : public sell_object {
int number_of_legs = 0;
public:
table(int number_of_legs) : number_of_legs(number_of_legs) { }
auto hash() const -> std::size_t override {
return std::hash<int>()(number_of_legs);
}
};
return (*lhs <=> *rhs) == 0;
This is a C++20 feature called the three-way comparison operator, sometimes called the spaceship operator. I opted into using it, since starting with C++20, most types that desire to be comparable will be using this operator. That means we also need our concrete classes to implement it. What's more, we need to be able to call it with base references (sell_object&). Yet another virtual function (operator, actually) needs to be added to the base class:
struct sell_object {
virtual auto hash() const -> std::size_t = 0;
virtual auto operator<=>(sell_object const&) const -> std::partial_ordering = 0;
};
Every subclass of sell_object is going to be required to be comparable with other sell_objects. The main reason is that we need to compare sell_objects in our storage map. For completeness, I used std::partial_ordering, since we require every sell_object to be comparable with every other sell_object. While comparing two books or two tables yields strong ordering (total ordering where two equivalent objects are indistinguishable), we also - by design - need to support comparing a book to a table. This is somewhat meaningless (always returns false). Fortunately, C++20 helps us here with std::partial_ordering::unordered. Those elements are not equal and neither of them is greater or less than the other. Perfect for such scenarios.
Our concrete classes need to change accordingly:
class book : public sell_object {
std::string title;
public:
book(std::string title) : title(std::move(title)) { }
auto hash() const -> std::size_t override {
return std::hash<std::string>()(title);
}
auto operator<=>(book const& other) const {
return title <=> other.title;
};
auto operator<=>(sell_object const& other) const -> std::partial_ordering override {
if (auto book_ptr = dynamic_cast<book const*>(&other)) {
return *this <=> *book_ptr;
} else {
return std::partial_ordering::unordered;
}
}
};
class table : public sell_object {
int number_of_legs = 0;
public:
table(int number_of_legs) : number_of_legs(number_of_legs) { }
auto hash() const -> std::size_t override {
return std::hash<int>()(number_of_legs);
}
auto operator<=>(table const& other) const {
return number_of_legs <=> other.number_of_legs;
};
auto operator<=>(sell_object const& other) const -> std::partial_ordering override {
if (auto table_ptr = dynamic_cast<table const*>(&other)) {
return *this <=> *table_ptr;
} else {
return std::partial_ordering::unordered;
}
}
};
The overriden operator<=>s are required due to the base class' requirements. They are quite simple - if the other object (the one we are comparing this object to) is of the same type, we delegate to the <=> version that uses the concrete type. If not, we have a type mismatch and we report the unordered ordering.
For those of you who are curious why the <=> implementation that compares two, identical types is not = defaulted: it would use the base-class comparison first, which would delegate to the sell_object version. That would dynamic_cast again and delegate to the defaulted implementation. Which would compare the base class and... result in an infinite recursion.
add() and remove() implementation
Everything seems great, so we can move on to adding and removing items to and from our shop. However, we immediately arrive at a hard design decision. What arguments should add() and remove() accept?
std::unique_ptr<sell_object>? That would make their implementation trivial, but it would require the user to construct a potentially useless, dynamically allocated object just to call a function.
sell_object const&? That seems correct, but there are two problems with it: 1) we would still need to construct an std::unique_ptr with a copy of passed argument to find the appropriate element to remove; 2) we wouldn't be able to correctly implement add(), since we need the concrete type to construct an actual std::unique_ptr to put into our map.
Let us go with the second option and fix the first problem. We certainly do not want to construct a useless and expensive object just to look for it in the storage map. Ideally we would like to find a key (std::unique_ptr<sell_object>) that matches the passed object. Fortunately, transparent hashers and comparators come to the rescue.
By supplying additional overloads for hasher and comparator (and providing a public is_transparent alias), we allow for looking for a key that is equivalent, without needing the types to match:
struct sell_object_hash {
auto operator()(std::unique_ptr<sell_object> const& object) const -> std::size_t {
return object->hash();
}
auto operator()(sell_object const& object) const -> std::size_t {
return object.hash();
}
using is_transparent = void;
};
struct sell_object_equal {
auto operator()(
std::unique_ptr<sell_object> const& lhs,
std::unique_ptr<sell_object> const& rhs
) const -> bool {
return (*lhs <=> *rhs) == 0;
}
auto operator()(
sell_object const& lhs,
std::unique_ptr<sell_object> const& rhs
) const -> bool {
return (lhs <=> *rhs) == 0;
}
auto operator()(
std::unique_ptr<sell_object> const& lhs,
sell_object const& rhs
) const -> bool {
return (*lhs <=> rhs) == 0;
}
using is_transparent = void;
};
Thanks to that, we can now implement shop::remove() like so:
auto remove(sell_object const& to_remove) -> void {
if (auto it = storage.find(to_remove); it != storage.end()) {
it->second--;
if (it->second == 0) {
storage.erase(it);
}
}
}
Since our comparator and hasher are transparent, we can find() an element that is equivalent to the argument. If we find it, we decrement the corresponding count. If it reaches 0, we remove the entry completely.
Great, onto the second problem. Let us list the requirements for the shop::add():
we need the concrete type of the object (merely a reference to the base class is not enough, since we need to create matching std::unique_ptr).
we need that type to be derived from sell_object.
We can achieve both with a constrained* template:
template <std::derived_from<sell_object> T>
auto add(T const& to_add) -> void {
if (auto it = storage.find(to_add); it != storage.end()) {
it->second++;
} else {
storage[std::make_unique<T>(to_add)] = 1;
}
}
This is, again, quite simple
*References: {1} {2}
Correct destruction semantics
There is only one more thing that separates us from the correct implementation. It's the fact that if we have a pointer (either smart or not) to a base class that is used to deallocate it, the destructor needs to be virtual.
This leads us to the final version of the sell_object class:
struct sell_object {
virtual auto hash() const -> std::size_t = 0;
virtual auto operator<=>(sell_object const&) const -> std::partial_ordering = 0;
virtual ~sell_object() = default;
};
See full implementation with example and additional printing utilities.

Abstract iterator for underlying collections

So basically what I want to do is to have a pure virtual method returning an iterator to an arbitrary collection of a concrete type, e.g in pseudo code:
virtual Iterator<T> getIterator() const = 0;
The user of this class actually don't care what implementation the child class uses. It could be a set, vector, list, array etc.
I'm aware of the std::iterator class but I cant find a way to specify it correctly in order to work with a simple vector.
virtual std::iterator<std::random_access_iterator_tag,T> getIterator() const = 0;
myVector.begin() // compilation error in implementation
defining std::iterator with const T as type parameter hasn't worked too. I also tried leaving T and instead defining the pointer and reference types as const T* and const T&.
By taking a look at the std::vector implementation, I found out that std::vector::const_iterator actually derives from _Iterator012 deriving from _Iterator_base.
It really bugs me that there isn't any way to work with arbitrary collections in std.
Implementing my classes as templates like in <algorithm> is not an option for me due two reasons:
No control over the actual value type
I simply don't want to make my classes templates complicating my design a lot and making things less flexible.
The used type parameter T was just for demonstration, actually this is a concrete type.
Here's a basic and very rudimentary skeleton approach using type erasure. You'll have to fill in a lot of missing details, though!
#include <memory>
template <typename T>
class TEIterator
{
struct TEImplBase
{
virtual ~TEImplBase() { }
virtual std::unique_ptr<TEImplBase> clone() const = 0;
virtual void increment() = 0;
virtual T & getValue() = 0;
T * getPointer() { return std::addressof(getValue()); }
};
template <typename Iter>
struct TEImpl
{
Iter iter;
TEImpl(Iter i) : iter(i) { }
virtual T & getValue()
{ return *iter; }
virtual std::unique_ptr<TEImplBase> clone() const
{ return std::unique_ptr<TEImplBase>(new TEImpl<Iter>(*this)); }
virtual void increment()
{ ++iter; }
};
std::unique_ptr<TEImplBase> impl;
public:
template <typename T>
TEClass(T && x)
: impl(new TEImpl<typename std::decay<T>::type>(std::forward<T>(x)))
{
}
TEClass(TEClass && rhs) = default;
TEClass(TEClass const & rhs) : impl(rhs.impl.clone()) { }
TEIterator & operator++()
{
impl->increment();
return *this;
}
T & operator*() { return impl->getValue(); }
T * operator->() { return impl->getPointer(); }
};
Usage:
std::vector<int> v;
std::deque<int> dq;
TEIterator<int> a = v.begin(), b = dq.end();
If you want to use a virtual method, you cannot use an arbitrary return value. What you can do, is define a base class, which is a wrapper around iterators, and subclass from that wrapper class.
But even then, you must restrict yourself to the smallest common denominator, since there are several iterator classes in the C++ standard library.
So, AFAICS, such a method with arbitrary iterators isn't really feasible without using templates.

How is SQL select usually implemented

I have two classes
class PopulationMember
{
public:
void operationOnThisMember1();
void operationOnThisMember2();
...
private:
Population* populaltion_;
}
class Population
{
public:
void operationOnAllMembers1();
void operationOnAllMembers2();
...
void operationOnAllMembers100();
void sortAllMembersCriterium1();
void sortAllMembersCriterium2();
...
void sortAllMembersCriterium100();
private:
QVector<PopulationMember*> members_;
}
I would like to implement a SELECT-like functionality to my framework. That is be able to perform operations only on those members which share a certain combination of properties.
So far I have thought out two approaches:
Implement a method that would return a new Population object composed of Members that satisfy a certain condition.
Popuation Popuation::select(bool (predicate*) (PopulationMember*));
Add a
bool selected_;
flag to each PopulationMember.
If I do 1. There is no way to implement sorting of selected data and deletion. If I do 2. There is overhead with checking for selectedness and I would have to reimplement sorting and other algorithms to operate only on selected members.
Is there a third, better way?
The approach I would take is to expose an iterator interface to the entire collection. To implement some sort of selection I would then use iterator adapters, e.g. one taking a unary predicate, which provide a new view of the range. This way there is neither an impact on the stored object nor any overhead in creating a separate collection. If you look at Boost's iterator adapters you may already get pretty much what is needed.
I have never looked, but I expect it will be method 1. See the MySQL source code to confirm my expectation. :-)
This is a proposal based on something similar i had to do once, which is an extended form of your first approach.
The advantage is the usage of STL's concepts and the freedom to either implement many functors or few parametrizable functors.
class All
{
public:
bool operator()(const PopulationMember* entity) const
{
return true;
}
};
class AscByID
{
public:
bool operator()(const PopulationMember* a, const PopulationMember* b) const
{
return a->getId() < b.getId();
}
};
template<typename Entity, class Predicate, class SortComparator>
class Query
{
public:
typedef std::set<Entity, SortComparator> ResultSet;
Query(const Predicate& predicate = Predicate(), const SortComparator& cmp = SortComparator()) :
predicate(predicate), resultSet(cmp)
{
}
bool operator()(const Entity& entity)
{
if (predicate(entity))
{
resultSet.insert(entity);
return true;
}
return false;
}
const ResultSet& getResult(void) const
{
return resultSet;
}
void clearResult(void)
{
resultSet.clear();
}
private:
Predicate predicate;
ResultSet resultSet;
};
int main()
{
Query<const PopulationMember*, All, AscByID> query;
Popuation::execute(query);
//do something with the result
query.getResult();
//clear the result
query.clearResult();
//query again
Popuation::execute(query);
//do something useful again
return 0;
}

Wrapping linked lists in iterators

A set of APIs that I commonly use follow a linked-list pattern:
struct SomeObject
{
const char* some_value;
const char* some_other_value;
SomeObject* next;
}
LONG GetObjectList( SomeObject** list );
void FreeObjectList( SomeObject* list );
This API is not mine and I cannot change it.
So, I'd like to encapsulate their construction/destruction, access, and add iterator support. My plan is to do something like this:
/// encapsulate access to the SomeObject* type
class MyObject
{
public:
MyObject() : object_( NULL ) { };
MyObject( const SomeObject* object ) : object_( object ) { };
const char* SomeValue() const
{
return NULL != object_ ? object_->some_value : NULL;
};
const char* SomeValue() const
{
return NULL != object_ ? object_->some_other_value : NULL;
};
private:
SomeObject* object_;
}; // class MyObject
bool operator==( const MyObject& i, const MyObject& j )
{
return // some comparison algorithm.
};
/// provide iterator support to SomeObject*
class MyObjectIterator
: public boost::iterator_adaptor< MyObjectIterator,
MyObject*,
boost::use_default,
boost::forward_traversal_tag >
{
public:
// MyObjectIterator() constructors
private:
friend class boost::iterator_core_access;
// How do I cleanly give the iterator access to the underlying SomeObject*
// to access the `next` pointer without exposing that implementation detail
// in `MyObject`?
void increment() { ??? };
};
/// encapsulate the SomeObject* creation/destruction
class MyObjectList
{
public:
typedef MyObjectIterator const_iterator;
MyObjectList() : my_list_( MyObjectList::Create(), &::FreeObjectList )
{
};
const_iterator begin() const
{
// How do I convert a `SomeObject` pointer to a `MyObject` reference?
return MyObjectIterator( ??? );
};
const_iterator end() const
{
return MyObjectIterator();
};
private:
static SomeObject* Create()
{
SomeObject* list = NULL;
GetObjectList( &list );
return list;
};
boost::shared_ptr< void > my_list_;
}; // class MyObjectList
My two questions are:
How do I cleanly give MyObjectIterator access to the underlying SomeObject to access the next pointer in the linked list without exposing that implementation detail in MyObject?
In MyObjectList::begin(), how do I convert a SomeObject pointer to a MyObject reference?
Thanks,
PaulH
Edit: The linked-list APIs I'm wrapping are not mine. I cannot change them.
First, of course, for real use, you almost certainly shouldn't be writing your own linked list or iterator at all. Second, good uses for linked lists (even one that's already written, debugged, etc.) are also pretty rare -- except in a few rather unusual circumstances, you should probably use something else (most often vector).
That said, an iterator is typically a friend (or nested class) of the class to which it provides access. It provides the rest of the world with an abstract interface, but the iterator itself has direct knowledge of (and access to) the internals of the linked list (or whatever container) to which it provides access). Here's a general notion:
// warning: This is really pseudo code -- it hasn't been tested, and would
// undoubtedly require a complete rewrite to even compile, not to mention work.
template <class T>
class linked_list {
public:
class iterator;
private:
// A linked list is composed of nodes.
// Each node has a value and a pointer to the next node:
class node {
T value;
node *next;
friend class iterator;
friend class linked_list;
public:
node(T v, node *n=NULL) : value(v), next(n) {}
};
public:
// An iterator gives access to the linked list.
// Operations:
// increment: advance to next item in list
// dereference: access value at current position in list
// compare: see if one iterator equals another
class iterator {
node *pos;
public:
iterator(node *p=NULL) : pos(p) {}
iterator operator++() {
assert(pos);
pos = pos->next;
return *this;
}
T operator*() { return pos->value; }
bool operator!=(iterator other) { return pos != other.pos; }
};
iterator begin() { return iterator(head); }
iterator end() { return iterator(); }
void push_front(T value) {
node *temp = new node(value, head);
head = temp;
}
linked_list() : head(NULL) {}
private:
node *head;
};
To work along with the algorithms in the standard library, you have to define quite a bit more than this tried to (e.g., typedefs like value_type and reference_type). This is only intended to show the general structure.
My advice: Trash this and use an existing slist<> implementation. IIRC, it will be in C++1x, so your compiler(s) might already support it. Or it might be in boost. Or take it from someplace else.
Wherever you get it from, what you get has all these problems already solved, is likely very well tested, therefore bug-free and fast, and the code using it is easily recognizable (looking at it many of us would immediately see what it does, because it's been around for a while and it's going to to be part of the next standard).
The last time I wrote my own list class was before the STL became part of the C++ standard library.
Ok, since you're stuck with the API you have, here's something that might get you started:
class MyObjectList
{
public:
typedef SomeObject value_type;
// more typedefs
class iterator {
public:
typedef SomeObject value_type;
// more typedefs
iterator(SomeObject* pObj = NULL)
: pObj_(pObj) {}
iterator& operator++() {if(pObj_)pObj_ = pObj_->next;}
iterator operator++(int) {iterator tmp(*this);
operator++();
return tmp;}
bool operator==(const iterator& rhs) const
{return pObj_ == rhs.pObj_;}
bool operator!=(const iterator& rhs) const
{return !operator==(rhs);}
value_type& operator*() {return pObj_;}
private:
SomeObject* pObj_;
};
class const_iterator {
public:
typedef SomeObject value_type;
// more typedefs
const_iterator(const SomeObject* pObj = NULL)
: pObj_(pObj) {}
iterator& operator++() {if(pObj_)pObj_ = pObj_->next;}
iterator operator++(int) {iterator tmp(*this);
operator++();
return tmp;}
bool operator==(const iterator& rhs) const
{return pObj_ == rhs.pObj_;}
bool operator!=(const iterator& rhs) const
{return !operator==(rhs);}
const value_type& operator*() {return pObj_;}
private:
const SomeObject* pObj_;
};
MyObjectList() : list_() {GetObjectList(&list_;);}
~MyObjectList() {FreeObjectList(list_);}
iterator begin() {return list_ ? iterator(list_)
: iterator();}
const_iterator begin() const {return list_ ? const_iterator(list_)
: const_iterator();}
iterator end () {return iterator(getEnd_());}
const_iterator end () const {return const_iterator(getEnd_());}
private:
SomeObject* list_;
SomeObject* getEnd_()
{
SomeObject* end = list_;
if(list_)
while(end->next)
end = end->next;
return end;
}
};
Obviously, there's more to this (for example, I believe const and non-const iterators should be comparable, too), but that shouldn't be hard to add to this.
From what you said, you probably have a BIG legacy code using your struct SomeObject types but you want to play nicely with new code and use iterators/stl containers.
If that's the case, you will not be able to (in an easy way) use your new created iterator in all the legacy code base, since that will be changing a lot of code, but, you can write a templated iterator that, if your structs follow the same pattern, having a next field, will work.
Something like this (I haven't tested nor compiled it, it's just an idea):
Suppose you have your struct:
struct SomeObject
{
SomeObject* next;
}
You will be able to create something like this:
template <class T>
class MyIterator {
public:
//implement the iterator abusing the fact that T will have a `next` field, and it is accessible, since it's a struct
};
template <class T>
MyIterator<T> createIterator(T* object) {
MyIterator<T> it(object);
return it;
}
If you implement your iterator correctly, you will be able to use all the STL algorithms with your old structs.
PS.: If you're in a scenario of some legacy code with this kind of structs, I do too, and I implemented this workaround. It works great.
You would make MyObjectIterator a friend of MyObject. I don't see any better way. And really I think it's reasonable that iterators get whatever special friend access is necessary for them to perform their duties.
You don't seem to have considered how and where your MyObject instance are going to be stored. Or perhaps that's what this question is coming out of. It seems like you would have to have a separate linked list of MyObjects in your MyObjectList. Then at least MyObjectList::begin() can just grab the first MyObject of your internal linked list of them. And if the only operations that may modify or rearrange this list only ever happen through the iterators you provide, then you can problem keep these lists in synch without too much trouble. Otherwise, if there are functions in the API you're using that take the raw SomeObject linked list and manipulate it, then you may have trouble.
I can see why you've tried to design this scheme, but having separate MyObjects that point to SomeObjects even through SomeObjects themselves make up the real list structure.... That is not an easy way to wrap a list.
The simplest alternative is just to do away with MyObject completely. Let your iterators work against SomeObject instances directly and return those when dereferenced. Sure that does expose SomeObject to the outside, particularly its next member. But is that really a big enough problem to justify a more complex scheme to wrap it all up?
Another way to deal with might be to have MyObject privately inherit from SomeObject. Then each SomeObject instance can be downcast as a reference to a MyObject instance and given to the outside world that way, thus hiding the implemtation details of SomeObject and only exposing the desired public member functions. The standard probably doesn't guarantee this will work, but in practice since they'll likely have the exact same memory layouts you may be able to get away with it. However, I'm not sure that I would actually ever try such a thing in a real program unless absolutely necessary.
The last alternative I can think of is just to transfer the data into a list of more convenient data structures after being given to you by this API. And then of course transfer it back into a raw SomeObject list only if necessary to pass it back to the API. Just make your own SomeObjectData or whatever to store the strings and put them in a std::list. Whether or not this is actually feasible for you really depends on how this data is used in the context of the API you've mentioned. If there are other API functions that modify SomeObject lists and you need to use them frequently, then constantly converting SomeObject lists to and from std::list<SomeObjectData> could be annoying.
I've seen some very good answers so far but I fear they might be "bare".
Before blindingly charge in let's examine the requirements.
As you noticed the structure is similar to a singly linked list, the C++0x standard defines such a structure, called forward_list. Read up its interface, yours should come close.
The iterator type will be ForwardIterator.
I would like to expose one very annoying fact though: who's responsible for the memory ?
I am worried because there's no copy facility in the interface you've provided, so should we disable the copy constructor and assignment operator of our new list class ?
Implementation is easy, there's enough on this page even though the iterator don't properly implement the iterator traits in general, but I would consider ditching this idea completely and move on to a better scheme:
class MyObject { public: ... private: SomeObject mData; };
Wrapping up GetObjectList and returning a deque<MyObject>, I guess the LONG returns the number of items ?

How to return a generic iterator (independent of particular container)?

I'd like to design a class Foo that stores various data of different types and returns iterators over them. It's supposed to be generic, so the user of Foo does not know how the data is stored (Foo could be using std::set or std::vector or whatever).
I'm tempted to write an interface like this:
class Foo {
class FooImpl;
FooImpl* impl_;
public:
const Iterator<std::string>& GetStrings() const;
const Iterator<int>& GetInts() const;
};
where Iterator is something like this (like iterators in .NET):
template<class T>
class Iterator {
public:
const T& Value() const = 0;
bool Done() const = 0;
void Next() = 0;
};
But I know that kind of iterator is not standard in C++, and it's better to use iterators the way the STL does, so you can use the STL algorithms on them.
How can I do that? (Do I need iterator_traits by any chance?)
Do you understand why the STL chose to put iterator implementation details in the header file? JIT frameworks are able to inline across compilation units, but C++ can only inline within a compilation unit. Advancing through a sequence is much faster when inlined, the cost of a function call dominates actually traversing the data structure.
If you really want to hide the implementation details, go ahead. You could make an STL-compatible iterator that implements operator++ and operator!= and operator-> in terms of protected virtual functions, the Next, Done, and Value you've mentioned would be decent names. Just expect to pay for the encapsulation with lower performance.
A c++ class with iterators has to provide at least two functions if they have to work with the std library
iterator begin() //returns an iterator at starting pos
iterator end() //returns an iterator one past end or just invald
The iterator has to overload the increment operators, equals and *
iterator operator++()
iterator operator==()//make sure that an invalid iterator equals end()
T& operator*()
You can use the iterator class to wrap around the iterator of the internal storage to ensure that the user is limited to these methods.
template <typename T> iter
{
iter(T::iterator& intern)
T::value_type& operator*(){return *intern}
iter operator++(){return iter(++intern);}
bool operator==(iter const& other)const{return intern == other.intern;}
}
Where T is the type of your container.(The class is incomplete and I may have mixed something up)
It almost looks like you're trying to create container-independent code, which is not (in general) a good idea, unless you are writing an algorithm which can operate solely with iterators. (See Scott Myers Effective STL Item 2: Beware the illusion of container-independent code)
The problem is that most of the standard containers do not provide overlapping functionality. If you're writing code for a particular container, assume you're writing code for that container. Don't bother trying to make it container-independent.
Use a typedef to return an boost::iterator_range. For example (never mind the names),
class Container
{
typedef std::vector<int> Collection;
public:
typedef boost::iterator_range<Collection::iterator> CollectionRange;
typedef Collection::iterator CollectionIterator;
Range range() const {
return make_iterator_range(collection_.begin(), collection_.end());
}
private:
Collection collection_;
};
The user code will be
Container c;
// ...
FOREACH(int i, c.range()) { //... }
Container::Range r = c.range();
for(Container::iterator j = r.begin(); j!= r.end(); j++) { // ... }
This is not generic, but the same idea can be used with templates.
To fulfill the requirement that the particular container (vector, set, ...) is not mentioned in the header file, and the user will be able to iterate over all strings, is to use the visitor pattern. The downside, of course, is that the user won't be able to use the STL algorithms on the strings.
// foo.h
class StringVisitor {
public:
void accept(const std::string& str) {
std::cout << str << std::endl;
}
};
class Foo {
class Impl;
Impl* impl_;
public:
Foo();
~Foo();
void VisitStrings(StringVisitor v) const;
};
// foo.cc
class Foo::Impl {
typedef std::vector<std::string> StringContainer;
StringContainer str_;
public:
Impl() {
str_.push_back("a");
str_.push_back("b");
}
void VisitStrings(StringVisitor v) const {
for(StringContainer::const_iterator it = str_.begin();
it != str_.end(); ++it){
v.accept(*it);
}
}
};
Foo::Foo() : impl_(new Impl()) {}
Foo::~Foo() {delete impl_;}
void Foo::VisitStrings(StringVisitor v) const {
impl_->VisitStrings(v);
}
// main.cc
int main() {
Foo foo;
foo.VisitStrings(StringVisitor());
return 0;
}