I have a class that contains the following virtual method:
struct point {
template<typename T>
virtual typename std::enable_if<std::is_base_of<point, T>::value, double>::type distTo(T &other) const = 0;
};
The above doesn't work because:
error: templates may not be ‘virtual’
The plan is to specialize the class by making more specific instances of it like point2D, point3D. However, I only want the function to work with types of the same class. So if point2D where to inherit this class, the method distTo should only take parameter of type point2D. How can I accomplish this?
This is what I had tried before I did the above:
virtual double distTo(point& other) = 0;
But when I override this method in the point2D class and try to replace the parameter with one of type point2D, I run into compiler errors.
Thanks for your time
This sounds like the Curiously Recurring Template Pattern. Furthermore, this is completely incompatible with dynamic indirection, as the compiler cannot statically verify the dynamic type (obviously). But the CRTP can only be used to implement the function, not declare it.
template<typename T> class Point {
public:
double distTo(T other) {
/* stuff */
}
};
class Point2D : public Point<Point2D> {
// distTo automatically defined
};
Fundamentally, the interface you are trying to declare is completely impossible because you're asking the compiler to statically typecheck dynamic types. There is no solution that offers all the properties you want.
I think your requirements make no sense for a static typed language such as C++.
Think about how would you be able to use your virtual function:
point2d p1, p2;
point3d p3;
point &p = p1;
p.distTo(p2); //ok?
p.distTo(p3); //error?
That is simply not possible, because at compile time the compiler will not know if p is a reference to a point2d or a point3d, only at runtime.
You could add an explicit cast and a runtime assertion if you do it wrong, but I think that it make little sense. Simply do:
struct point { /*...*/ };
struct point2d : point {
double distTo(const point2d &other);
};
struct point3d : point {
double distTo(const point3d &other);
};
And do not call distTo using base point references.
UPDATE: If you know that your list is homogeneous, but you don't know the cardinality, then you can do:
struct point {
virtual double distTo(const point &other) =0;
};
struct point2d : point {
double distTo(const point2d &other) { /*...*/ }
virtual double distTo(const point &other) {
const point2d &other2 = static_cast<const point2d &>(other);
return distTo(other2);
}
};
struct point3d : point {
double distTo(const point3d &other) { /*...*/ }
virtual double distTo(const point &other) {
const point3d &other3 = static_cast<const point3d &>(other);
return distTo(other3);
}
};
But beware! If you call point::distTo with a wrong object, the result will be undefined!
Related
In my C++ code, I have a collection of classes A1, A2, ..., all derived from a class A. I also have a vector v<*A> holding pointers to objects all of type A. I want to implement a function foo(A *x, A *y) that is dynamically ad hoc polymorphic in the type of x and y. To make this more concrete, imagine A is Shape, A1, A2, ..., are Circle, Rect, ..., and foo is intersects(Shape *x, Shape *y).
I could overload foo with declarations like foo(A1 *x, A2 *y) for the combinations of derived types of A that I care about, however this will not work for the objects referenced by my vector v since function overloading, unlike virtual methods, is handled statically. I also cannot use virtual methods of the form A1::foo(A2 *y) since this only dynamically resolves the type of the method's class (A1) and not the type of the argument (A2).
The only solution I've thought of is to implement foo as follows:
void foo(A *x, A*y) {
if (A1* a1 = dynamic_cast<A1*>(x)) {
if (A1* a1 = dynamic_cast<A1*>(y)) {
...
}
...
}
if (A2* a2 = dynamic_cast<A2*>(x)) {
if (A1* a1 = dynamic_cast<A1*>(y)) {
...
}
...
}
...
}
However, I've always been told that resorting to dynamic casts is rarely a good idea. Is there a more idiomatic way to achieve this?
This is double dispatch. The visitor pattern can accomplish this. You need a virtual function which makes the first type concrete to apply a visitor. And then you need another virtual function to make the second type concrete and return a visitor:
struct Shape
{
// Each derived class simply calls visit with the concrete type:
// return visitor.visit(*this);
virtual bool accept(const IntersectionVisitor& visitor) const = 0;
// Each derived class return a visitor which knows how to calculate
// the intersection of this particular class type with all types of
// shapes. The visit() overrides of this visitor have access to both
// concrete shape types.
virtual IntersectionVisitor intersection_visitor() const = 0;
};
struct IntersectionVisitor
{
// Calculate the intersection of this concrete shape with a Circle
virtual bool visit(const Circle&) = 0;
// Calculate the intersection of this concrete shape with a Rect
virtual bool visit(const Rect&) = 0;
};
bool intersects(const Shape& shape1, const Shape& shape2)
{
return shape2.accept(shape1.intersection_visitor());
}
Just because you can doesn't mean you should. You can do this more simply with variants:
using Shape = std::variant<Circle, Rect, ...>;
bool intersects(const Circle&, const Circle&) { ... }
bool intersects(const Circle&, const Rect&) { ... }
// all shape combinations, like before
// Visitation is just std::visit:
bool intersects(const Shape& shape1, const Shape& shape2)
{
return std::visit([](const auto& s1, const auto& s2) {
return intersects(s1, s2);
}, shape1, shape2);
}
I'm trying to write code which can find the distance between lots of different types of shapes. I've defined a base class Shape with a virtual distance(Shape& otherShape) function to find the distance to another shape and then want to define that for all my derived classes.
The problem is that there are lots of possible pairs of shapes, so my solution was to define a set of distance functions outside the classes (circle-circle, circle-square, square-tri etc.) and then call the corresponding one from the distance function. I've added a mini example of what I mean below, with just one derived class Circle to demonstrate the problem.
When I try and call my specific circleCircleDistance function I get an error because it can't convert the base class into the derived class. Is there any way I can address this or will my design as it stands just not work?
enum ShapeType{CIRCLE, SQUARE};
class Shape {
public:
ShapeType type;
virtual double distance(Shape& otherShape) = 0;
};
class Circle : public Shape {
public:
ShapeType type = CIRCLE;
double distance(Shape& otherShape) override;
};
double circleCircleDistance(Circle& circle1, Circle& cirlce2){
return 0; //pretend this does the calculation
};
double Circle::distance(Shape &otherShape) {
switch (otherShape.type){
case CIRCLE:
//Here I get the error
//cannot bind base class object of type Shape to derived class reference Circle& for 2nd argument
return circleCircleDistance(*this, otherShape);
}
}
You would have to cast the Shape& to a Circle&
return circleCircleDistance(*this, static_cast<Circle&>(otherShape));
As an aside, I'd handle your types a bit differently
class Shape {
public:
virtual ShapeType get_type() const = 0; // derived classes must override this
virtual double distance(Shape& otherShape) = 0;
};
class Circle : public Shape {
public:
ShapeType get_type() const override { return CIRCLE; } // here's your override
double distance(Shape& otherShape) override;
};
...
{
switch (otherShape.get_type()){
Otherwise you're going to get into a situation where type is shadowed from the derived/base classes depending how you access it.
Multiple dispatch is not natively supported in C++.
We only have single dispatch thanks to virtual method.
So you can implement double dispatch for your cases.
An (C++17) "alternative" option is to use std::variant, which has std::visit which implement multiple dispatch:
You can keep inheritance or drop it.
struct Circle {
Point center;
float radius;
};
struct Rectangle {
Point topLeft;
Point bottomRight
};
using Shape = std::variant<Square, Rectangle>;
double distance(const Square&, const Square&);
double distance(const Square&, const Rectangle&);
double distance(const Rectangle&, const Square&);
double distance(const Rectangle&, const Rectangle&);
double distance(const Shape& shape1, const Shape& shape2)
{
return std::visit([](const auto& shape1, const auto& shape2){
return distance(shape1, shape2);
},
shape1,
shape2);
}
In c++20 you could use template specialization with concepts for this kind of problem
Is it possible in C++ to formulate functions in the Base class that return Base type such that in the Derived class, they return Derived type, without overloading?
Minimal example:
class Base
{
public:
Base(double v)
{
value = v;
}
Base add(Base b)
{
return Base(b.value + this->value);
}
void print()
{
std::cout << value << std::endl;
}
double value;
};
class Derived : public Base
{
public:
Derived(double v) : Base(v)
{
}
void timesTwo()
{
value *= 2.0;
}
};
int main()
{
Derived d1(1), d2(2);
// This doesn't work because the result is of type Base
(d1.add(d2)).timesTwo();
return 0;
}
Motivation
In the actual example, Base represents a linear algebra matrix, and Derived represents a vector. The matrix offers many functions that are all applicable to vectors, such as addition or multiplication by a scalar.
In this case, it would be desirable not having to override all these matrix functions manually to return vectors. I would like to, if possible, express that whatever this type is, the return type should be identical to it.
Example:
class Matrix
{
...
Matrix operator*(double x);
};
class Vector : Matrix
{
...
};
Matrix M;
M = M * 2.0; // works
Vector v;
v = v * 2.0; // does not work, because v * 2.0 returns a Matrix
The effort for overriding e.g. operator*() for all derived classes is increased by the fact that there are derived classes for 3- and 2-dimensional vectors, etc.
I understand that a solution is to define a cast from Matrix to Vector (and to Vector3, Vector2, ...) but this would involve copying all entries (which are, for efficiency, stack arrays).
Is there a more efficient solution? And, if not, would it generally be considered cleaner/better to
duplicate all the relevant code in each derived class, or to
define a cast?
In my current understanding, the conflicting problems are:
Duplicate code makes the solution error-prone and more difficult to refactor.
Reusing existing code requires lots of copy operations every time the "scope" changes between Matrix, Vector, Vector3, ... . Would be inefficient if used in large calculations.
Any suggestion would be most appreciated. Thanks!
Yes, but only with free functions (including most operators).
template<class X, class Y,
std::enable_if_t<std::is_base_of<Base, std::decay_t<X>>{},int> =0,
std::enable_if_t<std::is_base_of<Base, std::decay_t<Y>>{},int> =0
>
friend X& operator+=(X&x, Y&& rhs)
{
x.value += rhs.value;
return x.
}
template<class X, class Y,
std::enable_if_t<std::is_base_of<Base, std::decay_t<X>>{},int> =0,
std::enable_if_t<std::is_base_of<Base, std::decay_t<Y>>{},int> =0
>
friend std::decay_t<X> operator+(X&&x, Y&& rhs) {
auto r=std::forward<X>(x);
r+=std::forward<Y>(rhs);
return r;
}
Now if I did that right,
(d1+d2).timesTwo();
works.
I also implemented + in terms of += because that usually works well.
The fancy enable if exists because koenig lookup with very generic template operators causes strange things to happen when you pass Base and types derived from Base to template types and proceed to use + on the resulting type. By saying "only things derived from Base", the right thing happens.
We need to use a template free friend function so we can get the type of "*this" (as it where) within the template to change our return type. This cannot be done in a template member function.
The enable_if clause does not work well in MSVC, but is best practice in other compilers. For MSVC use class=enable_if instead of enable_if=0. The reason why the =0 is best is out of scope here.
Make class Base abstract and put its methods in separated functions. Also declare pure virtual the methods you need in derived classes:
#include <iostream>
class Base
{
public:
Base(double v) : value(v) {}
double value;
virtual void timesTwo() = 0;
};
class Derived : public Base
{
public:
Derived(double v) : Base(v) {}
void timesTwo()
{
value *= 2.0;
std::cout << "timesTwo " << value << std::endl;
}
};
template <class T>
T add(const T& t1, const T& t2)
{
return T(t1.value + t2.value);
}
int main()
{
Derived d1(1), d2(2);
add(d1, d2).timesTwo();
return 0;
}
I want to overload + for Point+Point and Point+vector
class Vector
{
public:
double x;
double y;
double z;
};
class PointBase
{
public:
double x;
double y;
double z;
PointBase operator+(const Vector &vec) const
{
PointBase b;
b.x=vec.x+this->x;
b.y=vec.y+this->y;
b.z=vec.z+this->z;
return b;
}
};
class Point:public PointBase
{
public:
PointBase operator+(const Point &point) const
{
PointBase b;
b.x=point.x+this->x;
b.y=point.y+this->y;
b.z=point.z+this->z;
return b;
}
Point(PointBase& base)
{
}
Point()
{
}
};
int main()
{
Point p;
Vector v;
p=p+v;
return 0;
}
PointBase operator+(const Point &point) const hides PointBase operator+(const Vector &vec) const, why? I expect that 2 overloads work correctly: point+vector and point +point.
The operator+ in Point hides the one inherited from PointBase. To make it available, use
class Point:public PointBase
{
public:
using PointBase::operator+; // <-- here
PointBase operator+(const Point &point) const
// rest as before
Note, however, that the next problem you'll run into is that
p=p+v
attempts to use an operator= that takes a Point on the left and a PointBase on the right and that does not exist.
The reason that the operator+ in the derived class hides the one in the base class is the way name lookup works in C++: The compiler goes outward in layers (concrete class -> base class -> base base class -> ..., and for non-member functions called from a member function continues through the surrounding namespaces1) until it finds a matching name, tries to apply it, and fails if that doesn't work. You can see the same mechanism at work in this non-compiling piece of code:
void foo(char const *) { }
namespace bar {
void foo(int) { }
void baz() {
// does not compile: bar::foo hides ::foo
foo("hello");
}
}
In the case of your classes, the compiler looks in Point, finds a matching name, tries to apply it, and complains when it fails. It does not continue to look in the surrounding scope (PointBase), but it would continue to look if it had not found the operator+ in Point.
1 There's an asterisk for class templates that inherit other class templates here, where different mechanisms come into play. See Why do I have to access template base class members through the this pointer? for details, although none of that comes into play in your case.
Suppose we have an abstract class Element from which classes Triangle and Quadrilateral are derived from.
Suppose yet that these classes are used in conjunction with interpolation methods that depend on the shape of the element. So, basically we create an abstract class InterpolationElement from which we derive InterpolationTriangle and InterpolationQuadrilateral.
Then, to include the interpolation functionality in the Triangle and Quadrilateral classes, we add a const-reference data member in class Element of type InterpolationElement, that is:
class Element
{
public:
Element(const InterpolationElement& interp);
const InterpolationElement& getInterpolation() const;
private:
const InterpolationElement& interpolation;
};
We then create a method (as described by Scott Meyers, Effective C++) that instanciate a local static object of class InterpolationTriangle as
const InterpolationTriangle& getInterpolationTriangle()
{
static InterpolationTriangle interpolationTriangle;
return interpolationTriangle;
}
So that class Triangle can be constructed like:
class Triangle : public Element
{
public:
Triangle() : Element( getInterpolationTriangle() ) {}
};
Here is my question: is this approach correct in order to incorporate interpolation methods on my class Element? Is this used in professional scenarios?
I could implement directly all the interpolation methods on class Element (as pure virtual) and the override them in the derived classes Triangle and Quadrilateral. However, this approach seems to me to be cumbersome, since every time I need to improve or implement new interpolation functionalities I would have to do that on these classes. Moreover, the classes get bigger and bigger (many methods) using this approach.
I would like to hear from you some tips and comments
Thanks in advance.
Additional details:
class InterpolationElement
{
public:
InterpolationElement();
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
}
class InterpolationTriangle : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
class InterpolationQuadrilateral : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
:
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
}
The classes are used in conjunction with interpolation methods. Why do those methods need to be in a singleton object? The singleton here looks very problematic.
class Element
{
public:
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
};
class Triangle : public Element
{
public:
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
Also, welcome to SO!
This is reminiscent of a question that I had answered here. The same idea about the separation of data containers and the strategies.
There is one little issue with your proposal: you have added an interpolation related method to your base class and you've changed the constructor...
So first of all, if you wish to do it this way, here is how you should do it:
class Element
{
public:
private:
// similar signature to a `clone` method
virtual InterpolationElement* interpolation() const = 0;
};
class Triangle
{
public:
private:
virtual InterpolationTriangle* interpolation() const
{
return new InterpolationTriangle();
}
};
There are 2 advantages here:
It's no longer necessary to change the constructor of each of the derived objects
The strategy object is no longer const, which allows it to maintain state during the computation... like a reference to the current object being interpolated.
However, this still requires to change the Element class, and each of its derived classes. Doesn't it bother you ;) ?
Well, it's time (for once) to call upon a Design Pattern: Visitor.
It's a little different from the strategy idea, relying on double dispatch to work properly. However it allows you to tweak the hierarchy of Elements ONCE (with an accept method) and then to add as many operations as you wish. And that is great.
You can always mess a little bit with templates.
First we have a top class.
class Element {
public:
virtual void calculate() const = 0;
};
... but then we also have a class in the middle of the hierarchy which is actually a template. Template can't be the top level class, as templates with different parameters are different classes. The idea is that we give an interpolation class as a type parameter to the element.
template <typename Interpolation>
class Element_Impl : public Element {
protected:
Interpolation m_interpolation;
};
And interpolation classes. Notice, they aren't siblings, because they don't need to.
class InterpolationTriangle {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
And finally the real elements and the small main procedure.
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
m_interpolation.interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
m_interpolation.interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
Summary:
you can easily switch interpolation class for each element if needed.
there aren't double vtable access (first for Element's calculate and then for InterpolationElement's intepolate methods) as in the Matthieu's example. Each element knows at compile time which interpolation class it is using.
Element_Impl is an ugly bit, but it saves us from copypasta. You can expand it even further by implementing interpolation method wrappers
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
One way is to use static methods, and defining a wrapper in Element_Impl - still only in one place.
class Element {
public:
virtual void calculate() const = 0;
};
template <typename Interpolation>
class Element_Impl : public Element {
protected:
void interpolate(double, double) const {
Interpolation::interpolate(1, 1);
}
};
class InterpolationTriangle {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
What first comes to my mind is the GoF Design Pattern Visitor
From what I understand of your problem, this pattern is conceived to exactly solve this issue.
Each Visitor object defines an interpolation technique, or an algorithm to apply to your object.
Thus the Element class doesn't grow at all with each new functionnality. Once in place, the Visitor pattern enables to enrich functionnality without touching to the Base class definition.