I'd like to make two base classes (e.g. figure and move) with some children for each one(cube, sphere and so on for figure; shift, rotate, rescale and so on for moves). Initial number of figures and moves is unknown - it must be expandable. Each move should know how to move each figure, so having N figures and M moves means to have N*M function for them. (Adding a move requires creation of N functions for each already existing figure and adding figure requires creation of M functions for each already existing move).
The question is how to declare theese functions? For example, I'll have a class Set containing list of figures (aka vector) and I need to ask this class to move all the figures by i-th move. Probably set would have a method of
set::move_all (const move& )
and... well what next? The easiest idea is to create virtual method
class figure {
...
virtual void move_this (const move& )
...
}
to call a virtual method move_figure
class figure_i: public figure {
...
virtual void move_this (const move& M)
{M.move_figure(*this);
}
...
}
class move {
...
template <class T> virtual void move_figure (T&) const
...
}
and specialize it for each i-th move like this
template <> void shift::move_figure <cube> (cube& C)
{
}
and so on, but virtual templates are illegal.
You are making things more complicated than needed. You have a collection of objects (which you are calling figures) and a collection of actions (which you are calling moves). The obvious choice from an OOP perspective is to make the moves methods in your figures classes.
Update
Based on the comment below, you should be using a linear algebra library such as boost::ublas. There are others as well that you might want to look into such as Eigen (more or less shown below).
The basic idea is to abstract both the figures and the moves to generalize both so you don't have to rewrite the code for each possible combination. Thus, you would create a base class which looks something like:
template <typename T> class figure
{
std::vector<Eigen::Vector3d<T> > point_list;
...
void applyTransform(const Eigen::Affine3d<T>& src)
{
for (auto pt=point_list.begin(); pt != point_list.end(); pt++)
(*pt) = src * (*pt);
}
}
In this case, you define your point list based on the shape you are rendering. You can adjust meaning of the points in your derived classes to define specific geometric figures you're interested in. The Eigen::Affine3D class is used to define the transformations you want to apply. Eigen already has rotations and other affine transformations defined, so you should be able to reuse those.
You can also look into some specialized OpenGL or DirectX geometry classes which does all of this for you.
Well, my current solution is to use typeid/typeinfo to identify figure/move pair and call corresponding function (non-member) to move figure by this move from global object of map type like this
typedef pair<string, string> fm_pair_t;
typedef figure (*fm_act_f) (const figure& F, const move& M);
map<fm_pair_r, fm_act_f> global_fm_map;
class move {
...
figure move_figure (const figure& F) const
{map<fm_pair_r, fm_act_f>::const_iterator i =
global_fm_map.find (fm_pair_t(typeid(F).name(), typeid(*this).name()));
if (i == global_fm_map.end()) return F;
return i->second (F, *this);
}
...
};
and somewhere
figure cube_shift (const figure& _F, const move& _M)
{const cube& F = *dynamic_cast <const cube*> (&F);
const shift& M = *dynamic_cast <const shift*> (&M);
// act here with F and M like normal instances of cube and shift!
};
and, of course
global_fm_map(typeid(cube).name(), typeid(shift).name()) = cube_shift;
so unlike case of using templates, everything is independent and well expandable.
Related
Is it possible to perform double dispatch with runtime polymorphism?
Say I have some classes, and some of those classes can be added/multiplied/etc., and I want to store those dynamically within another class that performs type erasure at runtime. Then say I want to perform basic operations on the data held within that class.
The way to handle this (as far as I'm aware) is to use double dispatch to specialize the operation. However, all of the solutions I have encountered rely on the fact that you have a numerable amount of types, and then use virtual function calls or dynamic_casts, if-else, and RTTI to deduce the type at runtime. Because the data held within the class isn't known until runtime, I can't create a bunch of virtual methods or do a brute force check on the types. So I figured the visitor pattern would be the best solution, but even then, I can't seem to get whether or not this is possible.
I have a wrapper class that holds a smart pointer to a nested polymorphic class to implement the type erasure and runtime polymorphism, but I can't figure out if it's possible to use the visitor pattern to do double dispatch on this.
Note that the code below is incomplete, it just shows my thought process.
class Wrapper {
private:
class Concept;
template<typename T> class Model;
class BaseVisitor {
public:
virtual ~Visitor() = default;
virtual void visit(Concept &) = 0;
};
template<typename T>
class Visitor : public BaseVisitor {
private:
T first_;
public:
Visitor(T first) : first_(first) {}
virtual void visit(Concept &other) override {
// perform addition
}
};
class Concept {
public:
virtual ~Concept() = default;
virtual void add(Concept &m) const = 0;
virtual void accept(BaseVisitor &visitor) const = 0;
};
template<typename T>
class Model final : public Concept {
private:
T data_;
public:
Model(T m)
: data_(m) {}
virtual void add(Concept &m) const override {
Visitor<T> v(data_);
m.accept(v);
};
virtual void accept(BaseVisitor &visitor) const override {
visitor.visit(*this);
};
};
std::shared_ptr<const Concept> ptr_;
// This isn't right, it just illustrates what I'm trying to do.
// friend Something operator+(Wrapper &lhs, Wrapper &rhs) {
// return (*lhs.ptr_).add(*rhs.ptr_);
// }
public:
template<typename T>
Wrapper(T value) : ptr_(std::make_shared<Model<T>>(value)) {}
};
I've looked into implementing double dispatch using function pointers, template specialization, and static type IDs as well, but I can't seem to figure out how to make it work.
Is this even possible?
EDIT
Based on the comments below, in order to be more specific and to give a little more background, I am using templated classes that use template functions to perform basic operations like addition and multiplication. However, I would also like to store those templated classes within a vector, hence the type erasure. Now, if I wanted to do operations on those classes after I perform the type erasure, I need some way to deduce the type for the templated function. However, since I can't easily get the internal held type back from the Wrapper, I am hoping that there is a way I can call the correct template function on the data held within the Wrapper::Model<T> class, whether that is a visitor pattern, static type IDs, whatever.
To be even more specific, I am working with classes to do delayed evaluation and symbolic computations, meaning I have classes such as Number<T>, which can be Number<int>, Number<double>, etc. and classes such as Variable, Complex<T> and all of the TMP combinations for various operations, such as Add<Mul<Variable, Variable>, Number<double>>, etc.
I can work with all of these fine at compile-time, but then I need to be able to store these in a vector -- something like std::vector<Wrapper> x = {Number<int>, Variable, Add<Number<double>, Variable>};. My best guess at this was to perform type erasure to store the expressions inside the polymorphic Wrapper. This serves double-duty to enable runtime parsing support of symbolic expressions.
However, the functions I wrote to handle the addition, such as
template<typename T1, typename T2>
const Add<T1, T2> operator+(const T1 &lhs, const T2 &rhs)
{ return Add<T1, T2>(lhs, rhs); }
can't accept Wrapper and pull the type out (due to the type erasure). I can, however, insert the Wrapper into the Add expression class, meaning I can carry around the hidden types. The problem is when I actually get down to evaluating the result of something like Add<Wrapper, Wrapper>. In order to know what this comes out to, I'd need to figure out what's actually inside or to do something along the lines of double dispatch.
The main problem is that the examples for double dispatch that most closely match my problem, like this question on SO, rely on the fact that I can write out all of the classes, such as Shapes, Rectangles. Since I can't explicitly do that, I'm wondering if there's a way to perform double dispatch to evaluate the expression based on the data held inside the Model<T> class above.
I'm trying to build a Graph Datastructure based on an already existing Datastructure (which I cannot modify and which is not a graph itself).
I think I have somewhat a grasp on how to build most of the structure concerning the graph itself, but right now I have to reference back to the original data structure for one little "compare" function and having a really hard time how to model that properly...
My vertices represent two different classes A and B of the original data structure, that have different member variables and no common ancestors. For an algorithm I have to check whether two vertices are compatible.
The rule is: an A-Vertex and an B-Vertex are always incompatible, but if both vertices represent the same type I have to check some specifics for the respective type.
So the base idea is roughly like this:
bool isCompatible(const Vertex& other){
// if this->data is of other type than other->data
// return false;
// else return compareFunction(this->data, other->data)
// where maybe one could overload that compare-function
// or make a template out of it
}
But I don't really know how to store the reference to data without making it really ugly.
Idea 1) Use a void pointer for data, have some variable to store the type and then cast the void pointer into respective type
-> would probably work but seems really dangerous (type-safety?) and really ugly (basically no reusability for the Graph structure if you ever wanna use it on other data). Seems a bit like the brute force approach.
Idea 2) Make an abstract data class that offers some "isCompatible(data)" function, and have wrapper-classes for A and B respectively that inherit from the abstract class and override that function. Inside the overridden function one could use dynamic_cast then and compare the objects.
-> still doesn't seem like good design, but should also work?
Idea 3) Make templates work? It's my first time working with C++ so I'm having a few problems wrapping my head around that properly.
I think something like the following should work for comparing:
template<typename T1, typename T2>
bool compare(T1 object1, T2 object2){
return false;
}
And then having instances for (A,A) and (B,B) that override this. For me this seems like the way to got for the comparison itself. But I don't really know how to manage the reference from Vertex to the Object without losing the Type. Any suggestions?
I'm open to any other suggestions as well of course.
edit: I'm using C++11 if that's of relevance.
If your data is either an A or a B, where those two types have nothing in common, then sounds like what you want is a variant data type. The C++ standard library doesn't have one yet, but you could use Boost's:
boost::variant<A, B> data;
A variant gives you type safety (which void* doesn't) and doesn't require you to have a common ancestor between the two types (which apparently are conceptually unrelated).
With a variant like the above, you can implement your comparison using binary visitation:
bool isCompatible(const Vertex& other) {
boost::apply_visitor(is_compatible(), data, other.data);
}
with:
class is_compatible
: public boost::static_visitor<bool>
{
public:
template <typename T, typename U>
bool operator()( const T &, const U & ) const
{
return false; // cannot compare different types
}
bool operator()( const A& lhs, const A& rhs ) const
{
// whatever A-specific comparison
}
bool operator()( const B& lhs, const B& rhs ) const
{
// whatever B-specific comparison
}
};
I'm currently writing a small generic library for placing objects in a scene. The arrangement of the objects should be decided depending on the bounding box of the contents of the object. The class currently looks something like this:
template<class T>
class Object {
public:
Object() = default;
Object(const T& content, const Rect& bounding_box)
: _content(content)
, _bounding_box(bounding_box) {}
private:
T _content;
Rect _bounding_box;
};
Now, to construct the object we need to know the bounding box. Naturally it depends on the type T of the contents and might be quite complex to calculate (i.e. text).
My idea was that the user should supply its own Measurer which performs this calculation for his own content. An object could then be created by:
template <class T, class Measurer>
Object create_label(const T& value, Measurer op)
{
return Object(value, op(value));
}
Should this method be somehow incorporated into the Object class (something like a policy)? I was thinking something similar to allocators in the STL. Is there a generic design pattern for this kind of problem and how would you write such a class?
Also, should the constructor Object(const T& content, const Rect& bounding_box) be marked as protected, so that the user is pointed to the create_label method?
I think you want to look at static member functions. This type of method doesn't require (or have) an object to operate on so it is more like a global function BUT it has scope and visibility like a class method.
Factory methods such as your createLabel are typically declared within the class something like:
class Object {
public:
static Object createLabel(...);
}
Now because this is a static method you can call it directly without an instance:
Object O=Object.createLabel(...);
If you want to follow this strategy then your constructors SHOULD be private or protected to stop class users instantiating them directly. (BTW this works equally well for templated classes like yours)
There are various other strategies you might use to solve your particular problem which might be more convenient depending on your situation:
Define an abstract method called getMeasurer which much be defined
for each Object subclass - this seems to bind the Measurer more
solidly to the subclass both in the code and semantically.
Use partial template specification on the class / one method (this is
quite technical if you are not very familiar with c++)
You could make the signature of all your Object's constructors explicitly include
the measurer (and not the bounding box level)
EDIT: At OP's request some ideas on the partial template solution:
The most direct way it to simply declare a function inside the template definition like so
template<class T>
class Object {
.....
private:
BoundingBox measureMe();
}
Now as there is no *definition& supplied for measureMe (above is a declaration) any instantiated instamce of Object is going to cause a linker error as no MeasureMe() is defined.
But you supply specific implementations for specific types, so you can include definitions for various specific types:
BoundingBox Object<MyThing1>::measureMe()
{
... calculatethe size of a MyThing1
}
BoundingBox Object<MyThing2>::measureMe()
{
... calculate the size of a MyThing2
}
Now if you try to instantiate a object types for which you haven't defined a measureme on you still get an error; but the known types work as you wish.
Remember that you CAN still define a generic templated version of this function which will be used if there is no more specific version available which might be useful for you if most of your cases use the same logic but there are a few edge exceptions.
Why not just add another constructor that take measurer ?
template<class T>
class Object {
public:
Object() = default;
Object(const T& content, const Rect& bounding_box)
: _content(content)
, _bounding_box(bounding_box) {}
template<class Measurer>
Object(const T& content, Measurer op) : _content(content), _bounding_box(op(content)){}
private:
T _content;
Rect _bounding_box;
};
I am writing a scientific code which needs to create 3-dimensional cells, defined by a set of faces, which are defined by a set of vertices.
These 3 classes (Cell, Face, Vertex) are derived respectively from some generic geometry classes (Polyhedron, Polygon, Point) which implement some geometric routines like Polygon::CalculateArea().
The Face class adds to the Polygon class with additional data and functions required for the science, like Face::Interpolate(). I don't want to make these member functions virtual in the base class (Polygon).
Now, the problem. I initialize a Cell with a vector of pointers to Face, which is handled by the base class Polyhedron constructor, which upcasts the Face* to Polygon*:
Polyhedron::Polyhedron( std::initializer_list<Polygon*> polygons );
Later, I want to access the Face* stored in a Cell so that I can call Face::Interpolate(), but it has been stored as a Polygon* and thus has no member function Polygon::Interpolate(). I can downcast it manually back to a Face* which works, but is not very clean. The user of the code has to do something like:
Face * temp_face = (Face*)cell->GetFaces()[0]; // Could use static_cast
temp_face->Interpolate();
which is not obvious.
I want the interface to be transparent, so that this just works:
cell->GetFaces()[0]->Interpolate();
I can think of two or three ways to achieve this. I'm looking for a better solution or feedback of which of these is recommended:
In Cell::GetFaces() which currently just inherits from Polyhedron::GetPolygons() I could create a wrapper that copies the std::vector<Polygon*> to a new vector std::vector<Face*>. This seems sloppy to me, not easy to maintain, inefficient and prone to errors.
Instead of storing std::vector<Polygon*> I could store std::vector<std::shared_ptr<Polygon>>. From what I understand, these smart pointers retain type-awareness so that they can call the right destructor, but they might just store a reference to the destructor depending on implementation. I don't want to use shared_ptr for performance purposes -- I know they're good and friendly, but I'm creating millions of these Polygons and its easy to destroy them in the right place. I can't use unique_ptr easily because of the copy-constructor used in std::initializer_list constructors.
Template the whole Polyhedron class, replacing every instance of Polygon* with F* and checking that F is a base of Polygon:
template<typename F = Polygon>
typename std::enable_if<std::is_base_of<Polygon, F>::value, void>::type
class Polyhedron
and then inheriting from a parent with a given typename:
class Cell : public Polyhedron<Face>
This seems like the best method to me, since it has the least boilerplate and nothing exposed to the user; but it still feels messy, especially in the "real" case where there might be multiple types that would all have to be specified:
class Cell: public Polyhedron<Face,Vertex,type3,type4,type5,...>
Is there a a better way? Perhaps a means of retaining type in the original vector (or some other container)?
If not, which of the above methods is the best practice and why?
Edit:
Here's an abstracted view of the problem. The problem occurs when trying to run sumOfSomethingSpecific(). In my actual problem, that function is inside a derived class Derived_B, which is designed to work with Derived_A, but for the sake of the problem, it makes no difference.
class Base_A
{
public:
Base_A();
~Base_A();
// I don't want virtual doSomethingSpecific() here.
};
class Derived_A
{
public:
using Base_A::Base_A;
double doSomethingSpecific();
};
// I could template this whole class
// template <typename T>
// where T replaces Base_A
class B
{
public:
// This can be initialized with:
// std::vector<Derived_A*>
// which is what I want to do, but we lose info about doSomethingSpecific()
// even if I write a separate constructor its still stored as
// std::vector<Base_A*>
B(std::vector<Base_A*> v) : v(v) {};
~B();
double sumOfSomethingSpecific()
{
double sum = 0;
for(auto&& A : v) {
// Can't do this, A is a pointer of type Base_A*, but this is the abstraction that I want to achieve
sum += A->doSomethingSpecific();
// Could do this, but its ugly and error-prone
Derived_A* tempA = (Derived_A*)A;
sum += tempA->doSomethingSpecific();
}
return sum;
}
protected:
std::vector<Base_A*> v;
};
First most of issues you're facing here are not about programming, are about design.
... class with additional data and functions required for the science, like Face::Interpolate(). I don't want to make these member functions virtual in the base class (Polygon). ...
Well, don't do that, but then you have to realize that you're adding complexity to the code you need to implement such design desicion.
However, if every polygon can be "interpolated" then you should have a virtual function (or better yet a pure virtual function) in your Polygon class.
Said that, with the code as it is, in order to add transparency to the API you declare you get_* functions as:
void GetFaces(std::vector<Face *> &faces);
that way is clear for the user that he/she has to provide a reference to a vector of faces to get the result. Lets see how this change your code:
// Face * temp_face = (Face*)cell->GetFaces()[0]; // Could use static_cast
std::vector<Face *> temp_faces;
cell->GetFaces(temp_faces);
//temp_face->Interpolate();
temp_faces[0]->Interpolate();
This way the down-cast is performed implicitly.
About your question: Is there a a better way? Yes, redesign your classes.
About your example:
I will ask you to think a moment about this:
struct Base {};
struct Derived_A: Base { double doSomethingSpecific(); };
struct Derived_B: Base { double doSomethingSpecific(); };
int main()
{
std::vector<Base*> base_v = {/*suppose initialization here*/};
base_v[0]->doSomethingSpecific(); // Which function must be called here?
// Derived_A::doSomethingSpecific or
// Derived_B::doSomethingSpecific.
}
At some point you will have to tell wich type you want call the function on.
The level of abstraction you want, does not exists in C++. The compiler needs to know the type of an object in order to perform (compile) a call to one of its member functions.
Another approach you can try (I still recommend to redesign):
If you have the need of manipulating several distinct types in a uniform manner. Perhaps you want to take a look at Boot.Variant library.
I struggled with a similar problem in one of my projects. The solution I used was to give ownership of the actual objects to the most-derived class, give the base class a copy of the objects, and use a virtual function to keep the copy up-to-date as objects are added/removed:
class Polyhedron {
protected:
bool _polygons_valid = false;
std::vector<Polygon*> _polygons;
virtual void RebuildPolygons() = 0;
public:
std::vector<Polygon*>& GetPolygons()
{
if (!_polygons_valid) {
RebuildPolygons();
_polygons_valid = true;
}
return _polygons;
}
/*Call 'GetPolygons()' whenever you need access to the list of polygons in base class*/
};
class Cell: public Polyhedron {
private:
std::vector<Face*> _faces; //Remember to set _polygons_valid = false when modifying the _faces vector.
public:
Cell(std::initializer_list<Face*> faces):
_faces(faces) {}
//Reimplement RebuildPolygons()
void RebuildPolygons() override
{
_polygons.clear();
for (Face* face : _faces)
_polygons.push_back(face);
}
};
This design has the benefits of clear ownership (most-derived class is owner), and that copying and upcasting the vector of object pointers is done only when needed. The downside is that you have two copies of essentially the same thing; a vector of pointers to objects. The design is very flexible too, since any class derived from Polyhedron only has to implement the RebuildPolygons() function, using a vector of any type derived from Polygon.
Here it is explained in code:
//Sphere and Box inherit from IShape
//
//Sphere methods:
//bool Sphere::Intersect(Sphere* sphere)
//bool Sphere::Intersect(Box* box);
//
//Box methods:
//bool Box::Intersect(Sphere* sphere)
//bool Box::Intersect(Box* box)
IShape* shapeA;
IShape* shapeB;
shapeA= new Sphere();
shapeB= new Box();
bool areTheyIntersecting = shapeA->Intersect(shapeB); //problem is here?
Will such a way of using polymorphism ever work or must I look for another way to get the classes recognize each-other's types so they know the proper method to call?
The problem you are describing is known as double dispatch. There are many solutions. They all suck in various ways.
The fundamental reason why they suck is that double dispatch grows in size quadratically with the number of types, and writing a quadratic amount of code always sucks.
One approach is to figure out a way to reduce the general double dispatch to a single dispatch with a few special cases (like sphere sphere).
If the number of types is limited, you can have two sets of virtual functions. The first takes other as an abstract base class. The other set of functions has each implementation class as a possible argument. The abstract base class is implemented in each implementation calls the other other object with this as the first argument on the "other set of functions" that do not take the abstract base as an argument.
Ie, collide(base* other) calls other->collideSpecific (this).
CRTP can be used to reduce some of the boilerplate.
Double dispatch is generally used through the Visitor Pattern, but in your case it's a bit weird because the visitor is the element itself... hang on tight!
The idea, in a nutshell:
start from pair of IShape / IShape, named left and right from now on
invoke the intersect method on left passing right as argument, within the intersect method left knows it exact type (it's a Sphere!) and informs right about it by invoking the right overload of intersect on right (the one taking a Sphere)
within the intersect call on right, right knows its exact type and hey we passed the exact type of left too, so now we know them all!
A simple implementation:
class IShape {
public:
virtual ~IShape() {}
virtual bool intersect(IShape const& other) const = 0;
virtual bool intersect(Box const& other) const = 0;
virtual bool intersect(Sphere const& other) const = 0;
}; // class IShape
class Box: public IShape {
public:
virtual bool intersect(IShape const& other) const override {
std::cout << "-> Box::intersect(IShape)\n";
return other.intersect(*this);
}
virtual bool intersect(Box const& other) const override {
std::cout << "-> Box::intersect(Box)\n";
/* compute intersection of two boxes */
return false;
}
virtual bool intersect(Sphere const& other) const override {
std::cout << "-> Box::intersect(Sphere)\n";
/* compute intersection of a box and a sphere */
return false;
}
}; // class Box
// Likewise implementation of Sphere
A complete implementation gives this output:
int main() {
Box const box;
Sphere const sphere;
IShape const& ibox = box;
IShape const& isphere = sphere;
box.intersect(sphere);
// output
// -> Box::intersect(Sphere)
ibox.intersect(sphere);
// output
// -> Box::intersect(Sphere)
sphere.intersect(ibox);
// output
// -> Sphere::intersect(IShape)
// -> Box::intersect(Sphere)
isphere.intersect(ibox);
// output
// -> Sphere::intersect(IShape)
// -> Box::intersect(Sphere)
}
This strategy is named double dispatch because there are two consecutive double dispatches when starting from IShape/IShape, one dispatch per variable for which the dynamic type need be "deduced".
For this scenario you need something called double-dispatch. Take a look at More Effective C++ by Scott Meyers and Modern C++ Design by Alexendrescu.
Here is another article that also discusses it
http://www.drdobbs.com/double-dispatch-revisited/184405527
One way around it is to have uint variable declared in each class(or extractable from class, see below) and a virtual function returning this variable for the object in question. I'd then declare a hash of <std::pair<uint,uint>,std::function<bool(IShape*, IShape*)>>
The hash will contain functions that know how to deal with particular object types and typical call will be like:
auto key = std::pair<uint,uint>(obj1.typeNumber(), obj2.typenumber())
funchash[key](obj1, obj2);
The number does not even need to be hardcoded as shown in this manual :
http://shaderop.com/2010/09/uniquely-identifying-types-in-c-without-using-rtti/index.html
This essentially shows how to make class name into type id.
Sure, this still means a lot of boilerplate but I don't like having it inside my classes and this type mechanism is kinda useful itself anyway.