I suspect that the answer to this is "no" or "you're doing it wrong," but:
Is it possible to implement interface-type behavior WITHOUT using inheritance in C++ (11, if it matters)?
I have a couple of different structs,
struct Foo
{
float A;
void Bind()
{ .... }
};
struct Bar
{
float B;
void Bind()
{
}
};
... and others
These are operated on by a method that passes arrays of these structs to another process, and they have to be pretty tightly packed. If I use inheritance, creating a base class that implements the ::Bind() method, then the descendent classes have not only their data, but a VMT, which consumes a significant chunk of a very scarce resource. Other methods need to operate on these different types, but don't really care about the data members or the specifics of the ::Bind() method, which differs greatly between types.
In C# (or, I suspect, java), I'd do something like:
interface ICommon
{
void Bind();
}
struct Foo : ICommon
{
void Bind() { .... };
};
struct Bar : ICommon
{
void Bind() { ..... }
}
I could use a template:
template<typename T>
void Bind(T &item)
{
item.Bind();
}
but this introduces some constraint (ie, template needs to be declared in a header rather than a cpp, etc.) that are less than ideal. I'm aware of some hacks that let you put a template method implementation in the cpp file, but they're kind of messy and I'd rather avoid it.
This may be a "have your cake and eat it, too" request.
(Note that this isn't really a duplicate of other C++ Interfaces questions as I'm trying to avoid the oft-recommended solution of using multiple inheritance.)
You can achieve almost the same result using template parameters:
template <typename TRAIT>
class ICommon
{
TRAIT t;
public: void Bind()
{
t.Bind();
}
}
class FooTrait
{
public: void Bind() { .... };
};
class BarTrait
{
public void Bind() { ..... }
}
typedef ICommon<FooTrait> Foo;
typedef ICommon<BarTrait> Bar;
template <typename T>
void call_bind(ICommon<T> x)
{
x.Bind();
}
int main()
{
Foo f; Bar b;
call_bind(f);
call_bind(b);
}
Is it possible to implement interface-type behavior WITHOUT using inheritance in C++ (11, if it matters)?
Yes. Encapsulation is a viable alternative to inheritance.
You use the interfaces to define some behavior, then return the interface (the interface is still inherited, but not by your main class).
Example:
class IBinder {
virtual void Bind() = 0;
};
class Foo: public WhateverBaseClass {
struct Binder: public IBinder { virtual void Bind() override {} };
Binder b;
public:
IBinder& getBinder() { return b; }
};
Client code:
Foo f;
f.getBinder().Bind();
If you really don't want to use templates or inheritance, you could use overloaded free functions:
void Bind(Foo& foo) {}
void Bind(Bar& bar) {}
int main() {
Foo foo;
Bar bar;
Bind(foo);
Bind(bar);
}
Of course, any function that needs to operate on either type must be either overloaded or templated.
Java's interfaces are just a watered down way of doing evil, evil, cross my heart, we won't ever do that, multiple inheritance. Nothing more.
For your problem, if you want to get a bunch of objects that share an "interface," do as is natural: They belong to the interface's class, i.e., are derived from it. Can create an array of (pointers to) such objects, with a little care even of the objects themselves (but I wouldn't go there unless absolutely necessary, the danger of slicing off something is just too great).
Re: "templates only in headers": Says who? Headers are just included (probably in several different source files), in order to avoid writing the same declarations (and inline definitions) over and over. If you need templates, or classes, or whathaveyou just in a single source file, noboby will force you to create a header just for that.
Related
What I'm trying to do is to have a base class that has a primary functionality, as well as multiple derived classes that have various other additional functions/variables. The main functionality of all these derived classes will behave very similarly no matter what object of one of the derived classes is passed to it, but with slight changes based on what the derived class is.
So a background here is that I'm mostly experienced with Fortran programming but am trying to break into C++ more. I'm trying to do something here that is pretty easy in Fortran but am having trouble in C++. Basically my code defining my classes looks something like this
class base_class{
public:
void prim_func(base_class &my_obj);
};
class derived_class_1: public base_class{
public:
int a_func(int arg1);
};
class derived_class_2: public base_class{
public:
double a_func(double arg2);
};
And then the void class method looks something like (right now, I know this isn't right)
void base_class::prim_func(base_class &my_obj){
// a bunch of stuff for all classes
// if my_obj class is derived_class_1
my_obj.a_func(1);
// some more stuff specific to using derived_class_1
// if my_obj class is derived_class_2
my_obj.a_func(1.5);
// some more stuff specific to using derived_class_2
// a bunch of stuff for all classes
}
I want that prim_func to have (slightly) different behaviors based on what the actual derived class that is passed to it is. So the main code would look like this
derived_class_1 def_obj_1;
derived_class_2 def_obj_2;
main(){
def_obj_1.prim_func(def_obj_1);
def_obj_2.prim_func(def_obj_2);
}
So I would like to slightly modify the behavior in this primary functionality based on what the derived class of the passed object actually is. In Fortran there is a SELECT TYPE functionality (https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/a-to-z-reference/s-1/select-type.html) that allows this, but I can't seem to find something similar in C++?
I know one workaround could be to just make one big class that contains overloaded versions of all the different functions, and all the different variables that the various derived class objects would need, and then just have an indicator variable to let it know which functionality it should be using. But this would be extremely inelegant and would potentially cause some other issues, so I would like to avoid it.
You can't do that with plain C++.
You can't have derived classes with overriden functions with different signatures.
What you can do is using templates.
Use a templated Base Class that provides the base function as a pure virtual.
You can then write a wrapper around that function as a template:
template<typename T>
class Base {
public:
virtual T func(T param) = 0;
};
class DerivedA : public Base<int> {
public:
int func(int param) override {
return param;
};
};
class DerivedB : public Base<double> {
public:
double func(double param) override {
return param;
};
};
template<typename T>
T prim_func(Base<T>& base, T param) {
return base.func(param);
}
int main() {
DerivedA a;
DerivedB b;
auto c = prim_func(a,4);
auto d = prim_func(b,4.0);
}
Ok, so it turns out there is a way to do this in C++ it just involves dynamic casting a pointer using the passed object (but it does have to be a polymorphic object). So the way I made it work was doing something like this (comparing to the previous incomplete code I had).
class base_class{
public:
virtual void a_func(){};
void prim_func(base_class &my_obj);
};
class derived_class_1: public base_class{
public:
int a_func(int arg1);
};
class derived_class_2: public base_class{
public:
double a_func(double arg2);
};
void base_class::prim_func(base_class &my_obj){
// a bunch of stuff for all classes
if(derived_class_1* class_ptr = dynamic_cast<derived_class_1*>(&my_obj)){
class_ptr.a_func(1);
// some more stuff specific to using derived_class_1
}
else if(derived_class_2* class_ptr = dynamic_cast<derived_class_2*>(&my_obj)){
class_ptr.a_func(1.5);
// some more stuff specific to using derived_class_2
}
// a bunch of stuff for all classes
}
derived_class_1 def_obj_1;
derived_class_2 def_obj_2;
main(){
def_obj_1.prim_func(def_obj_1);
def_obj_2.prim_func(def_obj_2);
}
To be clear, this still won't compile/work since some of the functions need definitions and what not, but this is a general description of how to do it. A working example can be found in MFEM's code here: https://docs.mfem.org/4.5/amgxsolver_8cpp_source.html#l00859
I have the following very general problem that I have not found a satisfying solution to yet:
So I want to have two classes A and AData that are basically identical except that the latter has an additional attribute data and each of the classes supports a function foo(), which is different because it depends on the existence of the additional data.
The stupid solution is to copy the entire class and change it slightly, but that leads to code duplication and is hard to maintain. Using std::optional or a pointer lead to additional checks and therefore runtime overhead, right?
My question is whether there is a way to get the same runtime performance as just copying the code without actual code duplication? My current solution is to make AData a derived class and declare it as friend of A and then override the virtual function foo(), but I do not like this approach due to the use of friend.
You can use static polymorphism and curiosly recurring template pattern.
Both A and AData provide foo() but behaviour is class-specfic through doFoo(). Also not using virtual dispatch avoids runtime overhead of vtable lookup.
template <typename TData>
class Abase
{
public:
void foo()
{
static_cast<TData*>(this)->doFoo();
}
};
class A : public Abase<A>
{
friend ABase<A>;
void doFoo() { cout << "A::foo()\n"; }
};
class AData : public Abase<AData>
{
friend Abase<AData>;
int someDataMember;
void doFoo() { cout << "AData::foo()\n"; /*... use someDataMember ... */}
};
Live
Why not use composition:
class A
{
public:
void foo() { /*...*/ }
};
class AData
{
A a;
int someDataMember;
public:
void foo() { /*... use someDataMember ...*/ }
};
Please accept my apologies in advance for the somewhat long-winded question. This is the minimal self-contained example I could come up with... I'm pretty sure there must be some obvious/nice/neat solution to this problem, but I'm currently not able to see it.
Ok, here's the problem: Imagine the following situation (nb. a compileable version of the code is available at http://goo.gl/dhRNex). Suppose
struct Thing1 {
public:
void bar(class Implementation1 &i) {
i.baz();
}
// ...various other methods like bar()
};
struct Thing2 {
public:
void bar(class Implementation2 &i) {
i.qux();
}
// ...various other methods like bar()
};
are given. Unfortunately, these classes are fixed, i.e., can not be changed/refactored.
However, Implementation1 and Implementation2 are changeable. These two classes share a lot of similar code, so it seems natural to put the shared code in a common base class. However, the code is dependent the type of Thing used, but there is no common base class for Thing1 and Thing2, so it seems also natural to use templates. Thus, I came up with the following solution for the base class
template<class T, class S>
struct ImplementationBase {
public:
S *self;
void foo() {
T thing;
thing.bar(*self);
}
// ...lots more shared code like foo()
};
and concrete implementations
struct Implementation1 : public ImplementationBase<class Thing1, class Implementation1> {
public:
Implementation1() {
self = this;
}
void baz() {
std::cout << "Qux!" << std::endl;
}
};
struct Implementation2 : public ImplementationBase<class Thing2, class Implementation2> {
public:
Implementation2() {
self = this;
}
void qux() {
std::cout << "Qux!" << std::endl;
}
};
Ideally, one would use this instead of self in foo, but the problem is that this is of type ImplementationBase<class Thing1, class Implementation1>, but Implementation1 is required. Obviously, the whole thing is quite a mess and the Implementation and Thing classes are too tightly coupled, but I cannot see an easy way out without being able to refactor the Thing classes. So, finally, my questions are:
Is there a better alternative to using the self trick above?
Is there a design that would solve this problem in a better manner? (I have a feeling, there is, but that I'm missing something obvious)
If you have made it this far, thanks a lot for taking the time and reading the whole story and my apologies again for this long-winded question.
You're already using CRTP so you don't need the self at all:
template<class T, class S>
struct ImplementationBase {
public:
S* getThis() { return static_cast<S*>(this); }
void foo() {
T thing;
thing.bar(*getThis());
}
// ...lots more shared code like foo()
};
I need to store a container of pointers to objects.
These objects have some common methods/attributes (interface) that I want to enforce (possibly at compile time) and use.
Example:
struct A{
void fly(){}
};
struct B{
void fly(){}
};
A a;
B b;
std::vector<some *> objects;
objects.push_back(&a);
objects.push_back(&b);
for(auto & el: objects)
el->fly();
The simpler solution would be A and B inherit a common base class like FlyingClass:
struct FlyingClass{
void fly(){}
};
struct A: public FlyingClass { ...
struct B: public FlyingClass { ...
and create a
std::vector<FlyingClass *> objects;
This will work and also enforce the fact that I can only add to objects things that can fly (implement FlyingClass).
But what if I need to implement some other common methods/attributes WITHOUT coupling them with the above base class?
Example:
struct A{
void fly(){}
void swim(){}
};
struct B{
void fly(){}
void swim(){}
};
And i would like to do:
for(auto & el: objects) {
el->fly();
...
el->swim();
...
}
More in general i would be able to call a function passing one of these pointers and access both the common methods/attributes, like:
void dostuff(Element * el){
el->fly();
el->swim();
}
I could try to inherit from another interface like:
struct SwimmingClass{
void swim(){}
};
struct A: public FlyingClass, public SwimmingClass { ...
struct B: public FlyingClass, public SwimmingClass { ...
But then what the container should contain?
std::vector<FlyingClass&&SwimmingClass *> objects;
Sure, i could implement SwimmingFlyingClass, but what if i need RunningClass etc.. This is going to be a nightmare.
In other words, how can I implement a pointer to multiple interfaces without coupling them?
Or there is some template way of rethinking the problem?
Even run time type information could be acceptable in my application, if there is an elegant and maintainable way of doing this.
It is possible to do this, in a pretty TMP-heavy way that's a little expensive at runtime. A redesign is favourable so that this is not required. The long and short is that what you want to do isn't possible cleanly without language support, which C++ does not offer.
As for the ugly, shield your eyes from this:
struct AnyBase { virtual ~AnyBase() {} }; // All derived classes inherit from.
template<typename... T> class Limited {
AnyBase* object;
template<typename U> Limited(U* p) {
static_assert(all<is_base_of<T, U>...>::value, "Must derive from all of the interfaces.");
object = p;
}
template<typename U> U* get() {
static_assert(any<is_same<U, T>...>::value, "U must be one of the interfaces.");
return dynamic_cast<U*>(object);
}
}
Some of this stuff isn't defined as Standard so I'll just run through it. The static_assert on the constructor enforces that U inherits from all of T. I may have U and T the wrong way round, and the definition of all is left to the reader.
The getter simply requires that U is one of the template arguments T.... Then we know in advance that the dynamic_cast will succeed, because we checked the constraint statically.
It's ugly, but it should work. So consider
std::vector<Limited<Flying, Swimming>> objects;
for(auto&& obj : objects) {
obj.get<Flying>()->fly();
obj.get<Swimming>()->swim();
}
You are asking for something which doesn't make sense in general, that's why there is no easy way to do it.
You are asking to be able to store heterogeneus objects in a collection, with interfaces that are even different.
How are you going to iterate over the collections without knowing the type? You are restricted to the least specific or forced to do dynamic_cast pointers and cross fingers.
class Entity { }
class SwimmingEntity : public Entity {
virtual void swim() = 0;
}
class FlyingEntity : public Entity {
virtual void fly() = 0;
}
class Fish : public SwimmingEntity {
void swim() override { }
}
class Bird : public FlyingEntity {
void fly() override { }
}
std:vector<Entity*> entities;
This is legal but doesn't give you any information to the capabilities of the runtime Entity instance. It won't lead anywhere unless you work them out with dynamic_cast and rtti (or manual rtti) so where's the advantage?
This is pretty much a textbook example calling for type erasure.
The idea is to define an internal abstract (pure virtual) interface class that captures the common behavior(s) you want, then to use a templated constructor to create a proxy object derived from that interface:
#include <iostream>
#include <vector>
#include <memory>
using std::cout;
struct Bird {
void fly() { cout << "Bird flies\n"; }
void swim(){ cout << "Bird swims\n"; }
};
struct Pig {
void fly() { cout << "Pig flies!\n"; }
void swim() { cout << "Pig swims\n"; }
};
struct FlyingSwimmingThing {
// Pure virtual interface that knows how to fly() and how to swim(),
// but does not depend on type of underlying object.
struct InternalInterface {
virtual void fly() = 0;
virtual void swim() = 0;
virtual ~InternalInterface() { }
};
// Proxy inherits from interface; forwards to underlying object.
// Template class allows proxy type to depend on object type.
template<typename T>
struct InternalImplementation : public InternalInterface {
InternalImplementation(T &obj) : obj_(obj) { }
void fly() { obj_.fly(); }
void swim() { obj_.swim(); }
virtual ~InternalImplementation() { }
private:
T &obj_;
};
// Templated constructor
template<typename T>
FlyingSwimmingThing(T &obj) : proxy_(new InternalImplementation<T>(obj))
{ }
// Forward calls to underlying object via virtual interface.
void fly() { proxy_->fly(); }
void swim() { proxy_->swim(); }
private:
std::unique_ptr<InternalInterface> proxy_;
};
int main(int argc, char *argv[])
{
Bird a;
Pig b;
std::vector<FlyingSwimmingThing> objects;
objects.push_back(FlyingSwimmingThing(a));
objects.push_back(FlyingSwimmingThing(b));
objects[0].fly();
objects[1].fly();
objects[0].swim();
objects[1].swim();
}
The same trick is used for the deleter in a shared_ptr and for std::function. The latter is arguably the poster child for the technique.
You will always find a call to "new" in there somewhere. Also, if you want your wrapper class to hold a copy of the underlying object rather than a pointer, you will find you need a clone() function in the abstract interface class (whose implementation will also call new). So these things can get very non-performant very easily, depending on what you are doing...
[Update]
Just to make my assumptions clear, since some people appear not to have read the question...
You have multiple classes implementing fly() and swim() functions, but that is all that the classes have in common; they do not inherit from any common interface classes.
The goal is to have a wrapper object that can store a pointer to any one of those classes, and through which you can invoke the fly() and swim() functions without knowing the wrapped type at the call site. (Take the time to read the question to see examples; e.g. search for dostuff.) This property is called "encapsulation"; that is, the wrapper exposes the fly() and swim() interfaces directly and it can hide any properties of the wrapped object that are not relevant.
Finally, it should be possible to create a new otherwise-unrelated class with its own fly() and swim() functions and have the wrapper hold a pointer to that class (a) without modifying the wrapper class and (b) without touching any call to fly() or swim() via the wrapper.
These are, as I said, textbook features of type erasure. I did not invent the idiom, but I do recognize when it is called for.
There was an interesting problem in C++, but it was more about architecture.
There are many (10, 20, 40, etc) classes describing some characteristics (mix-in classes), for example:
struct Base { virtual ~Base() {} };
struct A : virtual public Base { int size; };
struct B : virtual public Base { float x, y; };
struct C : virtual public Base { bool some_bool_state; };
struct D : virtual public Base { string str; }
// ....
The primary module declares and exports a function (for simplicity just function declarations without classes):
// .h file
void operate(Base *pBase);
// .cpp file
void operate(Base *pBase)
{
// ....
}
Any other module can have code like this:
#include "mixing.h"
#include "primary.h"
class obj1_t : public A, public C, public D {};
class obj2_t : public B, public D {};
// ...
void Pass()
{
obj1_t obj1;
obj2_t obj2;
operate(&obj1);
operate(&obj2);
}
The question is how do you know what the real type of a given object in operate() is without using dynamic_cast and any type information in classes (constants, etc)? The operate() function is used with a big array of objects in small time periods and dynamic_cast is too slow for it and I don't want to include constants (enum obj_type { ... }) because this is not the OOP-way.
// module operate.cpp
void some_operate(Base *pBase)
{
processA(pBase);
processB(pBase);
}
void processA(A *pA)
{
}
void processB(B *pB)
{
}
I cannot directly pass a pBase to these functions. And it's impossible to have all possible combinations of classes, because I can add new classes just by including new header files.
One solution that came to mind, in the editor I can use a composite container:
struct CompositeObject
{
vector<Base *pBase> parts;
};
But the editor does not need time optimization and can use dynamic_cast for parts to determine the exact type. In operate() I cannot use this solution.
So, is it possible to avoid using a dynamic_cast and type information to solve this problem? Or maybe I should use another architecture?
The real problem here is about what you are trying to achieve.
Do you want something like:
void operate(A-B& ) { operateA(); operateB(); }
// OR
void operate(A-B& ) { operateAB(); }
That is, do you want to apply an operation on each subcomponent (independently), or do you wish to be able to apply operations depending on the combination of components (much harder).
I'll take the first approach here.
1. Virtual ?
class Base { public: virtual void operate() = 0; };
class A: virtual public Base { public virtual void operate() = 0; };
void A::operate() { ++size; } // yes, it's possible to define a pure virtual
class obj1_t: public A, public B
{
public:
virtual void operate() { A::operate(); B::operate(); }
};
Some more work, for sure. Notably I don't like the repetition much. But that's one call to the _vtable, so it should be one of the fastest solution!
2. Composite Pattern
That would probably be the more natural thing here.
Note that you can perfectly use a template version of the pattern in C++!
template <class T1, class T2, class T3>
class BaseT: public Base, private T1, private T2, private T3
{
public:
void operate() { T1::operate(); T2::operate(); T3::operate(); }
};
class obj1_t: public BaseT<A,B,C> {};
Advantages:
no more need to repeat yourself! write operate once and for all (baring variadic...)
only 1 virtual call, no more virtual inheritance, so even more efficient that before
A, B and C can be of arbitrary type, they should not inherit from Base at all
edit the operate method of A, B and C may be inlined now that it's not virtual
Disadvantage:
Some more work on the framework if you don't have access to variadic templates yet, but it's feasible within a couple dozen of lines.
First thing that comes to mind is asking what you really want to achieve... but then again the second thought is that you can use the visitor pattern. Runtime type information will implicitly be used to determine at what point in the hierarchy is the final overrider of the accept method, but you will not explicitly use that information (your code will not show any dynamic_cast, type_info, constants...)
Then again, my first thought comes back... since you are asking about the appropriateness of the architecture, what is it that you really want to achieve? --without knowledge of the problem you will only find generic answers as this one.
The usual object oriented way would be to have (pure) virtual functions in the base class that are called in operate() and that get overridden in the derived classes to execute code specific to that derived class.
Your problem is that you want to decide what to do based on more than one object's type. Virtual functions do this for one object (the one left of the . or ->) only. Doing so for more than one object is called multiple dispatch (for two objects it's also called double dispatch), and in C++ there's no built-in feature to deal with this.
Look at double dispatch, especially as done in the visitor pattern.