Using ranges-v3 to implement DFS - c++

I'm interested in using range-v3 to build and query linear quadtree data structures. I've been able to successfully use range-v3 to construct a linear quadtree data structure using existing views in the library. I'm excited to be able to express query logic as a view adaptor since you can iterate through nodes in the quadtree via advancing a RandomAccessIterator of the derived range, which conveniently helps separate out query behavior from the quadtree's structure.
My view adaptor has a single argument: a user-defined lambda predicate function that is used to evaluate a node and determine whether to step-in or step-out. Stepping in results in evaluating children nodes whereas stepping out results in visiting the next sibling (or potentially the node's parent's next sibling) until either a leaf node is successfully evaluated or we "exit" through the root node. (You can think of this as a DFS pattern.)
Thus, we are able to define this range in terms of a RandomAccessIterator (from the derived range) and a Sentinel (as opposed to another Iterator).
Here's some trimmed-down code that shows the overall structure. (My apologies if there is missing member data/structure):
template<typename Rng, typename Fun>
class quadtree_query_view
: public ranges::view_adaptor<quadtree_query_view<Rng, Fun>, Rng>
{
friend ranges::range_access;
using base_iterator_t = ranges::iterator_t<Rng>;
ranges::semiregular_t<Fun> fun;
uint tree_depth;
struct query_termination_adaptor : public ranges::adaptor_base
{
query_termination_adaptor() = default;
query_termination_adaptor(uint tree_depth) : tree_depth(tree_depth) {};
uint tree_depth;
uint end(quadtree_query_view const&) {
return tree_depth;
}
};
struct query_adaptor : public ranges::adaptor_base
{
query_adaptor() = default;
query_adaptor(ranges::semiregular_t<Fun> const& fun) : fun(fun) {};
ranges::semiregular_t<Fun> fun;
bool exited = false;
uint current_node_depth = 0;
base_iterator_t begin(quadtree_query_view const& rng) {
return ranges::begin(rng.base());
}
// TODO: implement equal?
// TODO: implement empty?
auto read(base_iterator_t const& it) const
{
return *it; // I'm not concerned about the value returned by this range yet.
}
CONCEPT_REQUIRES(ranges::RandomAccessIterator<base_iterator_t>())
void next(base_iterator_t& it ){
if (fun(*it)) { // Step in
// Advance base iterator (step in)
// Increment current_node_depth
} else { // Step out
// Advance base iterator (step out)
// Set "exited = true" if stepping out past root node.
// Decrement current_node_depth
}
}
};
public:
quadtree_query_view() = default;
quadtree_query_view(Rng&& rng, uint tree_depth, Fun fun)
: quadtree_query_view::view_adaptor{std::forward<Rng>(rng)}
, tree_depth(tree_depth)
, fun(std::move(fun))
{}
query_adaptor begin_adaptor() const {
return {std::move(fun)};
}
query_termination_adaptor end_adaptor() const {
return {tree_depth};
}
};
I'm trying to figure out the last few steps to complete this implementation:
My range does not satisfy the Range concept due to WeaklyEqualityComparable requirement not being implemented for my iterator/sentinel pair. What's the best way for going upon doing this?
Do I need to implement the equal member method for the query_adaptor? What do the two iterator arguments correspond to?
I'm assuming that I need to implement the empty member method for query_adaptor. Is this where the query exit criteria logic would go? Based on the documentation, the segment argument needs to be a type associated with the sentinel. Is this the same type that is returned by query_termination_adaptor::end(), e.g., a uint? Or does this need to be another type?
Thanks for any insights you can share. I'm really stoked to see ranges be incorporated into C++20!

Ah.
I was able to solve my problem by using default_sentinel. Since query_adaptor is meant to start at the root node and iterate in a single direction, I can remove end_adaptor and query_termination_adaptor all-together. I only had to implement a bool equal(default_sentinel) const { ... } method for the adaptor where I am able to determine if query exit criteria is met.
I'm still not sure why trying to implement a custom sentinel type caused issue for me. However, it did't provide any additional functionality over default_sentinel, other than owning tree_depth.

Related

C++ design choice

There is a class ActionSelection which has the following method:
ActionBase* SelectAction(Table* table, State* state);
ActionBase is an abstract class. Inside of the SelectAction method some action is fetched from the table considering the state if the table is not empty.
If the table is empty, a random action should be created and returned. However ActionBase is an abstract class, so can not be instantiated.
For different experiments/environments actions are different but have some common behavior (that's why there is an ActionBase class)
The problem is that this function (SelectAction) should return an experiment specific action, if the table is empty, however it does not know anything about the specific experiment. Are there any design workarounds of this?
It depends on whether empty tables...
Are expected to happen under normal circumstances
May happen under abnormal circumstances
Should never happen unless there is a bug in the program
Solution 1:
Include empty table handling into your control flow. As-is the function does not have enough information to react properly, so either :
Pass in a third parameter, containing a default action to return :
ActionBase *SelectAction(Table *table, State *state, ActionBase *defaultAction);
If you don't want to construct the default action unless it's needed, you can pass its type via a template parameter instead, optionally with additional parameters to construct it with :
template <class DefaultAction, class... DefActArgs>
ActionBase *SelectAction(Table *table, State *state, DefActArgs &&... args);
Let the caller handle it, by returning whether or not the operation was successful :
bool SelectAction(Table *table, State *state, ActionBase *&selectedAction);
Solution 2:
Throw an exception. It will bubble up to whoever can handle it. This is quite rarely used as a parameter check, since it should have been thrown by the object that should have produced a non-empty table in the first place.
ActionBase *SelectAction(Table *table, State *state) {
if(table->empty())
throw EmptyTableException();
// ...
}
Solution 3:
Setup an assertion. If your function received an empty table, something is broken, better halt the program and have a look at it with a debugger.
ActionBase *SelectAction(Table *table, State *state) {
assert(!table->empty());
// ...
}
Here is what I had in mind : It is not tested code but you get the idea.
1.
//header
class RandomActionBase : public ActionBase{
public
RandomActionBase();
static RandomAction* selectRandomAction();
protected:
static RandomActionBase* _first;
RandomActionBase* _next;
void register(RandomActionBase* r);
};
//implementation
RandomActionBase::_first = NULL;
RandomActionBase::RandomActionBase():_next(NULL){
if (_first==NULL) _first = this;
else _first->register(this);
}
void RandomActionBase::register(RandomActionBase* r)
{
if (_next==NULL) _next = r;
else _next->register(r);
}
RandomAction* RandomActionBase::selectRandomAction()
{
//count the number of randomactionbases
int count = 0;
RandomActionBase* p = _first;
while(p){
++count;
p = p->_next;
}
//now that you know the count you can create a random number ranging from 0 to count, I 'll leave this up to you and assume the random number is simply 2,
unsigned int randomnbr = 2;
RandomActionBase* p = _first;
while(randomnbr>0){
p= p->_next;
--randomnbr;
}
return p;
}
//header
class SomeRandomAction : public RandomActionBase{
public:
//implement the custom somerandomaction
}
//implementation
static SomeRandomAction SomeRandomAction_l;
The idea of course is to create different implementations of SomeRandomAction or even to pass parameters to them via their constructor to make them all distinct. For each instance you create they will appear in the static list.
Extending the list with a new imlementation just means to derive from RandomActionBase , implement it and make sure to create an instance, the base class is never impacted by this which make it even a design according to OCP.
Open closed principle. The code is extendable while not having to change the code that is already in place. OCP is part of SOLID.
2.
Another viable solution is to return a null object. It is quite similar as above but you always return the null object when the list is empty. Mind you a null object is not simply null. See https://en.wikipedia.org/wiki/Null_Object_pattern
It is simply a dummy implementation of a class to avoid having to check for null pointers to make the design more elegant and less susceptible for null pointer dereferencing errors.

Return type which depends on static parameter pack fields

I've recently been experimenting with parameter packs, since they seem to fill a pretty big need in my development. However, I've been running up against a problem for which parameter packs seem to be a feasible solution, but I can't figure out this particular issue. The issue at hand is how to take each type in the parameter pack, retrieve the n-th element from a static field in that type, and return that element (along with the others) in a tuple. In case that wording was a bit unclear, my current use-case is as follows:
/* WARNING: Possibly gratuitous detail */
The architecture of my program is that of an Entity-Component System. Essentially, there are multiple systems that define the logic of different areas of the program. These systems act on entities, which are composed of multiple components (which contain a specific piece of data, e.g. DescriptionComponent). Each system will verify that a given entity has all required components, then perform the system-specific logic.
To accomplish this, I have created a component base class from which specific components are derived. Each derived component contains a static vector which acts as a manager for all components of that type. Each component has an entityId field which references its owning entity, and the static vector is sorted on this id.
Currently, in a given system, I am able to find applicable entities by looking at the components which the system requires, then finding the sets of components which all contain the same entityId and performing the logic on those components. However, I am doing the logic to iterate through the static vectors of the components manually at this point, since each system will have different requirements in terms of component types.
A quick example, just in case the above wasn't clear:
Say DisplaySystem requires a PictureComponent and a PositionComponent. Now say the static fields managing these types are as follows:
PictureComponent::elements = [(picture: "somePic.jpg", id: 1), (picture: "otherPic.jpg", id: 2)]
PositionComponent::elements = [(pos: (1,2), id: 2), (pos: (4,5), id: 3)]
Currently, each component has its own iterator. Starting at zero, we bump up the component index with the lowest entityId (since the vectors are sorted on this key). In the above example, we'd try indices (0,0), see the id 1 is less than id 2, so bump the first index. Then we'd try (1,0), see that both components have entityId 2, and pass those to the system as a pair to perform logic on. Then we'd bump both indices, try (2,1), and be out of the bounds of the PictureComponent vector, and be done.
/* END Gratuitous detail */
The solution that I'd imagine for this problem would be a single templated parameter pack class which takes in the required component types and outputs tuples of components whose entityIds all match. The pseudo-code for this would be as follows
template <typename... RequiredComponentTypes>
class ComponentIterator {
/* standard input iterator functionality*/
...
array componentIndices // same size as our param pack, one index per type
tuple<RequiredComponentTypes...> getNextSetOfComponents() {
while every component's entity id is not equal:
find the currently indexed component with the lowest entity id;
increment the current index of that component type;
out of the while, once we have a set of components with the same entity id:
return a tuple of the indexed components for each type. **//this is the part I have no idea how to do**
}
}
As noted in the code, the process of returning a tuple whose values are retrieved from an index to the static field on the types is the part I'm unsure about. For any number of template parameters, it's trivial to do manually (if I have a set of named parameterized types, then making the tuple is as simple as calling make_tuple with the appropriate values.) However, when dealing with a parameter pack, I'm not sure how to get around the issue.
Any help you all could offer would be greatly appreciated, and if you need any clarification or more details, please don't hesitate to let me know. Thanks!
You may do something like:
template <typename... Ts>
class ComponentIterator {
static constexpr std::size_t size = sizeof...(Ts);
public:
ComponentIterator() : indices(), finished(false) { adjust(); }
std::tuple<Ts&...> get()
{
return get(std::index_sequence_for<Ts...>());
}
ComponentIterator& operator ++()
{
for (auto& e : indices) {
++e;
}
adjust();
return *this;
}
bool is_finished() const { return finished; }
private:
void adjust()
{
adjust(std::index_sequence_for<Ts...>());
}
template <std::size_t...Is>
std::tuple<Ts&...> get(std::index_sequence<Is...>)
{
return std::tie(Ts::elements[indices[Is]]...);
}
template <std::size_t...Is>
void adjust(std::index_sequence<Is...>) {
bool is_ended[size] = {indices[Is] == Ts::elements.size()...};
if (std::any_of(std::begin(is_ended), std::end(is_ended),
[](bool b) { return b; })) {
finished = true;
return;
}
int min_value = std::min({Ts::elements[indices[Is]].id...}) - 1;
for (;;)
{
++min_value;
bool increases[size] = {increase_until<Ts>(indices[Is], min_value)...};
if (std::any_of(std::begin(increases), std::end(increases),
[](bool b) { return !b; })) {
finished = true;
return;
}
const int ids[size] = {Ts::elements[indices[Is]].id...};
if (std::all_of(std::begin(ids), std::end(ids),
[min_value](int id) { return id == min_value;})) {
return;
}
}
}
template <typename T>
bool increase_until(std::size_t& index, int min_value)
{
for (; index != T::elements.size(); ++index) {
if (min_value <= T::elements[index].id) {
return true;
}
}
return false;
}
private:
std::array<std::size_t, size> indices;
bool finished;
};
Live example

Design Pattern for caching different derived types without using RTTI

Let's say I have a family of classes which all implement the same interface, perhaps for scheduling:
class Foo : public IScheduler {
public:
Foo (Descriptor d) : IScheduler (d) {}
/* methods */
};
class Bar : public IScheduler {
public:
Bar (Descriptor d) : IScheduler (d) {}
/* methods */
};
Now let's say I have a Scheduler class, which you can ask for an IScheduler-derived class to be started for a given descriptor. If it already exists, you'll be given a reference to it. If one doesn't exist, then it creates a new one.
One hypothetical invocation would be something like:
Foo & foo = scheduler->findOrCreate<Foo>(descriptor);
Implementing that would require a map whose keys were (descriptor, RTTI) mapped to base class pointers. Then you'd have to dynamic_cast. Something along these lines, I guess:
template<class ItemType>
ItemType & Scheduler::findOrCreate(Descriptor d)
{
auto it = _map.find(SchedulerKey (d, typeid(ItemType)));
if (it == _map.end()) {
ItemType * newItem = new ItemType (d);
_map[SchedulerKey (d, typeid(ItemType))] = newItem;
return *newItem;
}
ItemType * existingItem = dynamic_cast<ItemType>(it->second);
assert(existingItem != nullptr);
return *existingItem;
}
Wondering if anyone has a way to achieve a similar result without leaning on RTTI like this. Perhaps a way that each scheduled item type could have its own map instance? A design pattern, or... ?
The address of a function, or class static member, is guaranteed to be unique (as far as < can see), so you could use such an address as key.
template <typename T>
struct Id { static void Addressed(); };
template <typename ItemType>
ItemType const& Scheduler::Get(Descriptor d) {
using Identifier = std::pair<Descriptor, void(*)()>;
Identifier const key = std::make_pair(d, &Id<ItemType>::Addressed);
IScheduler*& s = _map[key];
if (s == nullptr) { s = new ItemType{d}; }
return static_cast<ItemType&>(*s);
}
Note the use of operator[] to avoid a double look-up and simplify the function body.
Here's one way.
Add a pure virtual method to IScheduler:
virtual const char *getId() const =0;
Then put every subclass to it's own .h or .cpp file, and define the function:
virtual const char *getId() const { return __FILE__; }
Additionally, for use from templates where you do have the exact type at compile time, in the same file define static method you can use without having class instance (AKA static polymorphism):
static const char *staticId() { return __FILE__; }
Then use this as cache map key. __FILE__ is in the C++ standard, so this is portable too.
Important note: use proper string compare instead of just comparing pointers. Perhaps return std::string instead of char* to avoid accidents. On the plus side, you can then compare with any string values, save them to file etc, you don't have to use only values returned by these methods.
If you want to compare pointers (like for efficiency), you need a bit more code to ensure you have exactly one pointer value per class (add private static member variable declaration in .h and definition+initialization with FILE in corresponding .cpp, and then return that), and only use the values returned by these methods.
Note about class hierarchy, if you have something like
A inherits IScheduler, must override getId()
A2 inherits A, compiler does not complain about forgetting getId()
Then if you want to make sure you don't accidentally forget to override getId(), you should instead have
abstract Abase inherits IScheduler, without defining getId()
final A inherits Abase, and must add getId()
final A2 inherits Abase, and must add getId(), in addition to changes to A
(Note: final keyword identifier with special meaning is C++11 feature, for earlier versions just leave it out...)
If Scheduler is a singleton this would work.
template<typename T>
T& Scheduler::findOrCreate(Descriptor d) {
static map<Descriptor, unique_ptr<T>> m;
auto& p = m[d];
if (!p) p = make_unique<T>(d);
return *p;
}
If Scheduler is not a singleton you could have a central registry using the same technique but mapping a Scheduler* / Descriptor pair to the unique_ptr.
If you know all your different subtypes of IsScheduler, then yes absolutely. Check out Boost.Fusion, it let's you create a map whose key is really a type. Thus for your example, we might do something like:
typedef boost::fusion::map<
boost::fusion::pair<Foo, std::map<Descriptor, Foo*>>,
boost::fusion::pair<Bar, std::map<Descriptor, Bar*>>,
....
> FullMap;
FullMap map_;
And we will use that map thuslly:
template <class ItemType>
ItemType& Scheduler::findOrCreate(Descriptor d)
{
// first, we get the map based on ItemType
std::map<Descriptor, ItemType*>& itemMap = boost::fusion::at_key<ItemType>(map_);
// then, we look it up in there as normal
ItemType*& item = itemMap[d];
if (!item) item = new ItemType(d);
return item;
}
If you try to findOrCreate an item that you didn't define in your FullMap, then at_key will fail to compile. So if you need something truly dynamic where you can ad hoc add new schedulers, this won't work. But if that's not a requirement, this works great.
static_cast the ItemType* to void* and store that in the map.
Then, in findOrCreate, just get the void* and static_cast it back to ItemType*.
static_casting T* -> void* -> T* is guaranteed to get you back the original pointer. You already use typeid(ItemType) as part of your key, so it's guaranteed that the lookup will only succeed if the exact same type is requested. So that should be safe.
If you also need the IScheduler* in the scheduler map just store both pointers.

Lambda with inner class implementing an interface

I am not very experienced with lambdas yet but I begin to like them very much and use them where it makes sense and where I feel they are the way to go.
Anyway, I have a class Tree that has a Tree::Visitor class with one virtual callback function called visit(/*args*/). That Visitor class does a recursive walk over all nodes. With this callback I am able to collect data from each node (or better I can extract paths of the tree (which is basically what I do with this function).
So I take a lambda and inside I use a class to implement the visit callback function by deriving from Tree::Visitor.
// Tree class, a rough view how it looks
class Tree {
// ...
// Visitor class for recursive walking the tree
class Visitor {
//
void count(/* ... */) {
// in here the implemented visit(/*args*/) fct is called
}
// ...
void triggerVisit() {
// ...
count(/* ... */);
// ...
}
// visitor callback
virtual void visit(/* args */) = 0;
};
};
class A {
Tree tree;
PriorityQueue que;
A() : tree(), que(maxEntries) {}
// first build the tree ...
void buildTheTree() {
tree.buildTree();
}
// walk the tree
void visitTheTree() {
std::shared_ptr<Tree::Visitor>(
[&]()->Tree::Visitor * {
// this class implements visit(/*args*/)
class MyVisitor : public Tree::Visitor {
A& parent; // pointer to A
Myvisitor(A& p)
: Tree::Visitor(p.tree), parent(p) {}
// implementation
virtual void visit( /* args */ ) {
// ... get somedata
if (/* condition true */) {
parent.que.push(somedata);
}
}
};
return new MyVisitor(*this);
}()
)->triggerVisit();
// get the collected data from que
while(que.size() > 0) {
// ...
}
}
};
Basically this is what I have and it is working without problems.
I have a priority queue que that I use to store somedata, that are the n top scored nodes of the tree. At this time that que is defined as a member of class A, which I dislike, because I just need to collect the data inside the visitTheTree member, so it could be rather a local variable
So my question is more a question of design/style and I have the feeling I miss something with the c++11 standard (maybe).
I tried to define que inside visitTheTree() and pass it with the constructor of MyVisitor. Somehow this is not working correctly, at least I do not get proper/complete results I expect. When I define the Priority queue variable as a member of A (as it is now) and access it with the parent pointer in MyVistor, I get proper results and all is fine.
Is there any good way to define que locally in VisitTheTree() instead of defining it in the class A as a member? I know I have to pass it with the constructor as I can not access variables outside the MyVistor (just like this).
BTW, I found the question C++0x - lambda expression does look same as Java's anonymous inner class? which comes close to the problem/question I have. Interesting is the answer from Johannes.
Any hints or ideas would be welcome. Thanks for your thoughts and help!
Andreas, I would really like to help you, but I cannot see a way to do it using your design. I had a similar situation using boost graph library, and I made the following (hope it helps you):
Visitor has a std::function<RET (/*args*/> member that is used to make an action every node you visit. I would also make this function a parameter for the visitor constructor.
Every time you need to visit some nodes you will make it through a new instance of your visitor passing a new lambda function as the argument.
I would try to provide some example,
class Tree {
...
typedef std::function<void (/*node and args*/)> visit_fn;
class Visitor {
visit_fn& visitor;
public:
Visitor( visit_fn f ) : visitor( f ) {}
...
};
};
class A {
...
void visit_tree() {
que.clear(); // could also be a local queue object
Visitor vis([&](/*args*/) {
que.push( some_data ); /*I have que because of & in my lambda*/
});
vis.triggerVisit();
// Her I can use my queue member
}
};
Now, if you have a commom way to visit your elements you can even pass a Functor to your Visitor, providing better code reuse.
I really think that the lambda in your design is not using the [&] binding, and in this sense could be a common function, wich I think would be more clean, reusable and efficient.

Iterating a changing container

I am iterating over a set of callback functions. Functions are called during iteration and may lead to drastic changes to the actual container of the functions set.
What I am doing now is:
make a copy of original set
iterate over copy, but for every element check whether it still exists in the original set
Checking for every element's existence is super-dynamic, but seems quite slow too.
Are there other propositions to tackle this case?
Edit : here is the actual code :
// => i = event id
template <class Param>
void dispatchEvent(int i, Param param) {
EventReceiverSet processingNow;
const EventReceiverSet& eventReceiverSet = eventReceiverSets[i];
std::copy(eventReceiverSet.begin(), eventReceiverSet.end(), std::inserter(processingNow, processingNow.begin()));
while (!processingNow.empty()) {
EventReceiverSet::iterator it = processingNow.begin();
IFunction<>* function = it->getIFunction(); /// get function before removing iterator
processingNow.erase(it);
// is EventReceiver still valid? (may have been removed from original set)
if (eventReceiverSet.find(ERWrapper(function)) == eventReceiverSet.end()) continue; // not found
function->call(param);
}
};
Two basic approaches come to mind:
use a task based approach (with the collection locked, push tasks onto a queue for each element, then release all parties to do work and wait till completion). You'll still need a check to see whether the element for the current task is still present/current in the collection when the task is actually starting.
this could leverage reader-writer locks for the checks, which is usually speedier than fullblown mutual exclusions (especially with more readers than writers)
use a concurrent data structure (I mean, one that is suitable for multithreaded access without explicit locking). The following libraries contain implementations of concurrent data structures:
Intel Thread Building Blocks
MS ConCrt concurrent_vector
libcds Concurrent Data Structures
(adding links shortly)
There is a way to do it in two steps: first, go through the original set, and make a set of action items. Then go through the set of action items, and apply them to the original set.
An action item is a base class with subclasses. Each subclass takes in a set, and performs a specific operation on it, for example:
struct set_action {
virtual void act(std::set<int> mySet) const;
};
class del_action : public set_action {
private:
int item;
public:
del_action(int _item) : item(_item) {}
virtual void act(std::set<int> mySet) const {
// delete item from set
}
};
class upd_action : public set_action {
private:
int from, to;
public:
upd_action(int _from, int _to) : from(_from), to(_to) {}
virtual void act(std::set<int> mySet) const {
// delete [from], insert [to]
}
};
Now you can create a collection of set_action*s in the first pass, and run them in the second pass.
The operations which mutate the set structure are insert() and erase().
While iterating, consider using the iterator returned by the mutating operations.
it = myset.erase( it );
http://www.cplusplus.com/reference/stl/set/erase/