Contravariance in abstract classes

I would like to create a nice interface in C ++, on which each implementation should have a specific definition, in itself.

I would like to do something like this:

class A{ ... virtual A& operator+(const A& other) =0; ... } // this is my interface or abstract class. class B : A{ ... B& operator+(const B& other); ... } // this is the kind of implementation i would like. a B element can be added by another B element only ! At least this the constraint I am aiming at. 

since C ++ does not accept contravariance, my B& operator+(const B& other) function does not implement virtual A& operator+(const A& other) . Is there any tricky (but slightly clean ...) way to do this?

+6
source share
2 answers
 template<class Y> class A { virtual Y& operator+=(const Y& other) = 0; }; class B : A<B> { // must implement B& operator+=(const B& other) else B is abstract }; 

- one of the methods. This idiom is common when implementing policies. See http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

+6
source

What you are trying to do is impossible in any language, because it does not make sense.

It is true that methods are contravariant in argument types in some languages, but this means that a method is overload if it accepts a supertype. That is, operator+(const A&) will be an overload for operator+(const B&) . But not the other way around. Because when you have two instances of A (call them x and y ) and write x + y , the method will be called and the compiler cannot know if both will be from the same subtype as this information. be available at runtime. So, at runtime, this is the only time you can check it.

So:

  • If you need an interface and it will use it polymorphically, then the operator should take the interface and check at runtime that it received a compatible instance (but this does not inspire confidence in the design).
  • If you do not need to use it polymorphically, do not bother to define the interface at all. Just use + in the template that will use it (it should be a template if it is not polymorphic), and the compiler will judge when it is not defined. You can write a concept validation class to learn early and avoid mistakes with a too deep template extension stack.
+5
source

Source: https://habr.com/ru/post/977984/


All Articles