My first foray in to C++ is building an audio synthesis library (EZPlug).
The library is designed to make it easy to set up a graph of interconnected audio generator and processor objects. We can call the EZPlugGenerators
All of the processor units can accept one or more EZPlugGenerators as inputs.
Its important to me that all configuration methods on these EZPlugGenerators are chainable. In other words, the methods used in setting up the synthesis graph should always return a pointer to the parent object. That allows me to use a syntax which very nicely shows the nested nature of the object relationships like this:
mixer.addGenerator(
a(new Panner())
->setVolume(0.1)
->setSource(
a(new TriggererPeriodic())
->setFrequency(
v(new FixedValue(1), "envTriggerFreq")
)
->setTriggerable(
a(new Enveloper())
->setAllTimes(v(0.0001), v(0.05), v(0.0f, "envSustain"), v(0.01))
->setAudioSource(
a(new SineWaveMod())
->setFrequency(
a(new Adder())
->addGenerator(a(new Adder()))
->addGenerator(v(5000, "sineFreq"))
->addGenerator(
a(new Multiplier())
->addVal(v("sineFreq"))
->addVal(
a(new TriggererPeriodic())
->setFrequency(v("envTriggerFreq"))
->setTriggerable(
a(new Enveloper())
->setAllTimes(0.1, 0.1, 0, 0.0001)
->setAudioSource(v(1, "envAmount"))
)
)
)
)
)
)
)
);
The "a" and "v" functions in the above code store and return references to objects and handle retrieving them and destroying them.
I suspect my approach to C++ looks a little weird, but I'm finding that the language can actually accommodate the way I want to program fairly well.
Now to my question
I'd like to create a common superclass for all EZPlugGenerators which can accept inputs to inherit from. This superclass would have a method, "addInput", which would be overridden by each subclass. The problem comes from the fact that I want "addInput" to return a pointer to an instance of the subclass, not the superclass.
This isn't acceptable:
EZPlugProcessor* addInput(EZPlugGenerator* generator)
because that returns a pointer to an instance of the superclass, not the sublass destroying the chainability that I'm so happy with.
I tried this:
template<typename T> virtual T* addInput(EZPlugGenerator* obj){
but the compiler tells me I can't create a virtual template function.
I don't HAVE to use inheritance here. I can implement 'addInput' on every single EZPlugGenerator that can take an input. It just seems like gathering all of them under a single parent class will help make it clear that they all have something in common, and will help enforce the fact that addInputis the proper way to plug one object in to another.
So, is there a way I can use inheritance to dictate that every member of a group of classes must implement an 'addInput' method, while allowing that method to return a pointer to an instance of the child class?
Virtual functions in C++ can have covariant return types, which means that you can define
virtual EZPlugProcessor *addInput(EZPlugGenerator* generator) = 0;
in the base class, and then
struct MyProcessor : EZPlugProcessor {
virtual MyProcessor *addinput(EZPlugGenerator* generator) {
...
return this;
}
};
As long as the caller knows (by the type they're using) that the object is a MyProcessor, they can chain addInput together with other functions specific to MyProcessor.
If your inheritance hierarchy has more levels, then unfortunately you'll sometimes find yourself writing:
struct MySpecificProcessor : MyProcessor {
virtual MySpecificProcessor *addinput(EZPlugGenerator* generator) {
return static_cast<MySpecificProcessor*>(MyProcessor::addInput(generator));
}
};
because there's no way to specify in EZPlugProcessor that the return type of addInput is "pointer to the most-derived type of the object". Each derived class has to "activate" the covariance for itself.
Yes, C++ already provides for covariant return types.
class Base
{
public:
virtual Base* add() = 0 { return <some base ptr>; }
};
class Child : public Base
{
public:
virtual Child* add() { return <some child ptr>; }
};
On the other hand no one will ever be able to read your code so you might want to consider if there's an alternate way to set up the configuration than writing LISP chaining in C++.
Related
I'm pretty experienced in C++, but I find myself struggling with this particular design problem.
I want to have a base class, that I can stuff in a std::map, with a virtual function that can be called generically by a method that is querying the map. But I want to be able to call that function from a base class pointer with different parameters, depending on what the derived type is. Something functionally similar to the following wildly illegal example:
class Base
{
virtual void doThing() = 0;
}
class Derived1 : public Base
{
void doThing(int i, const std::string& s) {} // can't do that
}
class Derived2: public Base
{
void doThing(double d, std::vector<int>& v) {} // can't do that either
}
enum class ID = {
DERIVED1,
DERIVED2
}
std::map<ID, std::unique_ptr<Base> thingmap = { ... }
std::unique_ptr<Base>& getThing(int) { return thingmap[i] };
int main(int I, const char* argv[]) {
auto baseptr = getThing(DERIVED1);
baseptr->doThing(42, "hello world");
}
I don't want the caller to have to know what the derived type is, only that a Derived1 takes an int and a string. Downcasting isn't an option because the whole point of this is that I don't want the caller to have to specify the derived type explicitly. And C-style variable argument lists are yucky. :-)
Edited to clarify: I know exactly why the above can't possibly work, thank you. :-) This is library code and I'm trying to conceal the internals of the library from the caller to the greatest extent possible. If there's a solution it probably involves a variadic template function.
You can't do that.
Your map is filled with Base instances, so the class DO NOT have the required prototypes implemented in Derived1 or Derived2... And redefining overloaded methods do not implement the pure virtual method doThing, so Derived1 and Derived2 are still abstract classes and therefore cannot be instanciated.
Worst, your getThing function only deals with Base, so the compiler would NEVER allows you to use the overloaded signatures, since they don't exist AT ALL in Base. There is nothing to know the real class behind, since you don't use templates and implicit template argument deduction.
Your pattern cannot be done this way, period. Since you don't want to use neither downcasting nor explicitely specified child classes, you're stuck.
Even if you add all possible prototypes in Base, since it will be pure virtual methods, both derived classes will still be abstract classes. And if they aren't, then you'll never be able to know which one is a NOP and which one is implemented, since it will requires downcasting!
I think that you made a common mistake, even done by expert developers sometimes: you went into conception directly, BEFORE determining your real ROOT needs.
What you ask looks like the core system of a factory, and it's really not the good way to implement this design pattern and/or designing the specialized derived classes.
Sorry if the question title makes no sense, but I'm not sure how to succinctly describe the problem I'm trying to solve. Here's the issue:
I'm working with a C++ library that makes heavy use of a class which we'll call Base
This library has several different child classes that inherit from Base. We'll call these classes Child1, Child2, .. etc.
This library allows the user create their own child classes of Base and have the library use instances of those classes. I currently have something like this:
class Custom : public Child1 // inherit from Child1, which inherits from Base
{
public:
// override virtual functions here
// ...
void doSomething(); // Utility function I created
}
and then the library I'm using will have some function like this:
void foo(Base* base);
I can pass in a pointer to my Custom class no problem, everything's fine. There are also times where I might need to receive a pointer to a Base object from the library and do stuff with it. That looks something like this:
// code...
Base *base = getSomeBase(); // getSomeBase() is a function from the library that returns a Base*
Custom* myCustom = static_cast<Custom*>(base); // I always make the library use my `Custom` class, so this is safe.
myCustom->doSomething();
This also works without issue. I'm able to invoke my custom doSomething() method by performing a static_cast. However...I now have the need to have more than one possible Custom class. Specifically, I need make the appropriate "child" class to inherit from a template parameter in my Custom class. My code now looks like this:
template <class Child_t>
class Custom : public Child_t // inherit from Child_t, which inherits from Base
{
public:
// override virtual functions here
// ...
void doSomething(); // Utility function I created
}
There is no issue in making the library use my new templated Custom<> class because as long as the template parameter Child_t is in fact one of the library's child classes that inherit from Base, my Custom<> class can simply be cast to a Base*. The issue arises when trying to go in the other direction:
Base *base = getSomeBase();
/* ?????
Would like to call base->doSomething();
But I have no idea which Custom class I have received here. "base" could be
a Child1*, Child2*, etc. There's no way for me to perform a cast.
*/
I am stuck. Note that my function doSomething() will have identical behavior regardless of which Custom<> class I have received from the library. My initial thought was to move my doSomething() function to an interface class.
class Interface
{
public:
virtual void doSomething() = 0;
}
And then have each Custom<> class implement the interface like so:
template <class Child_t>
class Custom : public Child_t, public Interface
{
void doSomething() override;
}
This ends up being unhelpful, as the compiler will not allow me to do the following:
Base *base = getSomeBase();
Interface* interface = static_cast<Interface*>(base); // Error: can't static_cast between unrelated types.
interface->doSomething();
The compiler says that Interface and Base are unrelated types. I know for a fact that any Base* I receive is actually an Interface*, but the compiler can't know that and, I'm guessing, cannot perform the correct pointer adjustment to convert the Base* to an Interface*. At this point I'm stuck and am not sure what to do. I need to call my doSomething() function on whatever Base* I get from the library, but I have no idea which custom child class I'm actually getting. The only solution I currently see is to exhaustively dynamic_cast to every possible child class.
Base *base = getSomeBase(); // getSomeBase()
if (auto* c1 = dynamic_cast<Custom<Child1>*>(base))
{
c1->doSomething();
}
else if (auto* c2 = dynamic_cast<Custom<Child2>*>(base))
{
c2->doSomething();
}
This is an ugly solution. It also places extra cognitive load on the developer because if at any point they decide they need to use a Custom<Child3>, Custom<Child4>, Custom<Child5>, etc. class, they must remember to go back and update the if-else chain to exhaustively check for each possible case. So my question is:
Is it possible to somehow invoke my doSomething() function on the Base* object without actually knowing which Custom<> class I have at compile time, and without simply trying every possible dynamic_cast? Hence the title of my question: can I somehow cast a Base* to an Interface*, given that I know for a fact that they share a common child class (I just don't know which child class).
Am I going about this in the completely wrong way?
you should use dynamic_cast<Interface*>(base)
struct B{virtual ~B(){}};
struct I{virtual int foo()=0;};
struct X:B{};
struct Y:I,X{virtual int foo(){return 10;}};
struct Z:I,X{virtual int foo(){return 20;}};
int main(){
B* x = new Z;
I* i = dynamic_cast<I*>(x);
return i->foo();
}
http://coliru.stacked-crooked.com/a/f7a5787cb9fe80be
I have three classes of objects:
class Foo: has a mesh, and I need to get that mesh;
class Bar: is a Foo, but has some further capabilities which Foo doesn't have;
class Baz: is a Foo, but has another completely independent set of capabilities which neither Foo nor Bar have.
All three classes need to have a way to give me their mesh which, however, can be implemented in many ways, of which I need (at the moment I can't see another way) to use at least 2 different ones, which are MeshTypeA and MeshTypeB.
I would like to have a common interface for different implementations of the same concept (getMesh), however, I can't use auto in a virtual method. I'm lacking the facility to make the code have sense. I would like to have:
class Foo
{
public:
virtual ~Foo() = 0;
virtual auto getMesh() const = 0; // doesn't compile
};
class Bar : public Foo
{
public:
virtual ~Bar() = 0;
virtual auto getMesh() const = 0; // doesn't compile
// other virtual methods
};
class ConcreteFooWhichUsesA : public Foo
{
public:
ConcreteFooWhichUsesA();
~ConcreteFooWhichUsesA();
auto getMesh() const override {return mesh_;};
private:
MeshTypeA mesh_;
};
class ConcreteBarWhichUsesB : public Bar
{
public:
ConcreteBarWhichUsesB();
~ConcreteBarWhichUsesB();
auto getMesh() const override {return mesh_;};
// other implementations of virtual methods
private:
MeshTypeB mesh_;
};
MeshTypeA and MeshTypeB are not exclusive to Foo, Bar, or Baz, which is to say all three could have both types of mesh. However I really don't care for which MeshType I get when I later use it.
Do I need to wrap MeshTypeA and MeshTypeB in my own MeshType? Is it a matter of templating the MeshType? I believe there is a way, however related questions aren't helping or I can't formulate my question in a meaningful enough way.
I have also found this where the author uses a Builder class and decltype, but I don't have such a class. Maybe that would be it? Do I need a MeshLoader sort of class as an indirection level?
If your MeshTypes all have a common (abstract) base class, then you can just return (a pointer or reference to) that in the virtual function defintions, and the derived classes can then return their concrete mesh types, and all will be well. If you have code that can work on any mesh type, it is going to need that abstract base anyways.
If your MeshTypes do not all have a common base class, why even have a getMesh method in Foo at all? Remove it and give each of the concrete classes it's own getMesh method that doesn't override (and has nothing in particular to do with the meshes in any other concrete class).
A function's return type is part of its interface. You can't just change it willy-nilly. More specifically, you cannot have a base class virtual method return one thing while an overridden version returns another. OK, you can, but only if the derived version's return type is convertible to the base class return type (in which case, calling through the base class function will perform said conversion on the overriding method's return type).
C++ is a statically typed language; the compiler must know what an expression evaluates to at compile time. Since polymorphic inheritance is a runtime property (that is, the compiler is not guaranteed to be able to know which override will be called through a base class pointer/reference), you cannot have polymorphic inheritance change compile-time constructs, like the type of a function call expression. If you call a virtual method of a base class instance, the compiler will expect this expression to evaluate to what that base class's method returns.
Remember: the point of polymorphic inheritance is that you can write code that doesn't know about the derived classes and have it still work with them. What you're trying to do violates that.
I'm experiencing a challenging problem, which has not been solvable - hopefully until now. I'm developing my own framework and therefore trying to offer the user flexibility with all the code complexity under the hood.
First of all I have an abstract base class which users can implement, obviously simplified:
class IStateTransit
{
public:
bool ConnectionPossible(void) = 0;
}
// A user defines their own class like so
class MyStateTransit : public IStateTransit
{
public:
bool ConnectionPossible(void){ return true; }
}
Next, I define a factory class. Users can register their own custom state transit objects and refer to them later by simply using a string identifier they have chosen:
class TransitFactory : public Singleton<TransitFactory>
{
public:
template<typename T> void RegisterStateTransit(const string& name)
{
// If the transit type is not already registered, add it.
if(transits.find(name) == transits.end())
{
transits.insert(pair<string, IStateTransit*>(name, new T()));
};
}
IStateTransit* TransitFactory::GetStateTransit(const string& type) const
{
return transits.find(type)->second;
};
private:
map<string, IStateTransit*> transits;
}
Now the problem is (probably obviously) that whenever a user requests a transit by calling GetStateTransit the system currently keeps returning the same object - a pointer to the same object that is. I want to change this.
PROBLEM: How can I return a new (clone) of the original IStateTransit object without the user having to define their own copy constructor or virtual constructor. Ideally I would somehow like the GetStateTransit method to be able to cast the IStateTransit object down to the derived type it is at runtime and return a clone of that instance. The biggest hurdle is that I do not want the user to have to implement any extra (and probably complex) methods.
4 hours of Googling and trying has led me nowhere. The one who has the answer is a hero!
The problem is that you don't have the type information to perform the clone as you only have a pointer to base class type and no knowledge as to what derived types have been implemented and are available.
I think there's a reason that 4 hours of googling haven't turned anything up. If you want IStateTransit to be cloneable you have to have an interface where the derived class implementer provides some sort of clone method implementation.
I'm sorry if this isn't what you wanted to hear.
However, implementing a clone method shouldn't be a big burden. Only the class implementor knows how a class can be copied, given a correct copy constructor, clone can be implemented for a leaf-node class like this:
Base* clone() const
{
return new MyType(*this);
}
You could even macro-alize it; although I wouldn't.
If I understand the problem correctly, you shouldn't insert new T -s into the map, but rather objects that create new T-s.
struct ICreateTransit
{
virtual ~ICreateTransit() {}
virtual IStateTransite* create() const = 0;
};
template <class T>
struct CreateTransit: public ICreateTransit
{
virtual IStateTransit* create() const { return new T(); }
};
And now insert:
transits.insert(pair<string, ICreateTransit*>(name, new CreateTransit<T>()));
And retrieve "copies" with:
return transits.find(type)->second->create(); //hopefully with error handling
It shouldn't be impossible to modify StateTransit<T> so it holds a T of which to make copies of, should the default one not do.
I think the general name for techniques like this is called "type erasure" (derived types "remember" particular types, although the base class is unaware of those).
This problem to me sounds that the abstract factory pattern might be of help. Using this pattern the libraries client can define how your framework builds its types. The client can inject his own subclass of the factory into the framework and define there what types should be build.
What you need is (additionaly)
A base class for the factory
As a client: Derive a concrete factory
A way to inject (as a client) a subtype of the factory into the framework
Call the factory metods to create new types.
Does this help you?
How do you 'de-serialize' a derived class from serialized data? Or maybe I should say, is there a better way to 'de-serialize' data into derived classes?
For example, suppose you had a pure virtual base class (B) that is inherited by three other classes, X, Y and Z. Moreover, we have a method, serialize(), that will translate X:B, Y:B and Z:B into serialized data.
This way it can be zapped across a socket, a named pipe, etc. to a remote process.
The problem I have is, how do we create an appropriate object from the serialized data?
The only solution I can come up with is including an identifier in the serialized data that indicates the final derived object type. Where the receiver, first parses the derived type field from the serialized data, and then uses a switch statement (or some sort of logic like that) to invoke the appropriate constructor.
For example:
B deserialize( serial_data )
{
parse the derived type from the serial_data
switch (derived type)
case X
return X(serial_data)
case Y
return Y(serial_data)
case Z
return Z(serial_data)
}
So after learning the derived object type we invoke the appropriate derived type constructor.
However, this feels awkward and cumbersome. I'm hoping there is a more eloquent way of doing this. Is there?
In fact, it's a more general issue than serialization called Virtual Constructor.
The traditional approach is to a Factory, which based on an ID returns the right derived type. There are two solutions:
the switch method as you noticed, though you need to allocate on the heap
the prototype method
The prototype method goes like so:
// Cloneability
class Base
{
public:
virtual Base* clone() const = 0;
};
class Derived: public Base
{
public:
virtual Derived* clone() const { return new Derived(*this); }
};
// Factory
class Factory
{
public:
Base* get(std::string const& id) const;
void set(std::string const& id, Base* exemplar);
private:
typedef std::map < std::string, Base* > exemplars_type;
exemplars_type mExemplars;
};
It is somewhat traditional to make the Factory a singleton, but it's another matter entirely.
For deserialization proper, it's easier if you have a virtual method deserialize to call on the object.
EDIT: How does the Factory work ?
In C++ you can't create a type you don't know about. The idea above is therefore that the task of building a Derived object is given to the Derived class, by way of the clone method.
Next comes the Factory. We are going to use a map which will associate a "tag" (for example "Derived") to an instance of an object (say Derived here).
Factory factory;
Derived derived;
factory.set("Derived", &derived);
Now, when we want to create an object which type we don't know at compile time (because the type is decided on the fly), we pass a tag to the factory and ask for an object in return.
std::unique_ptr<Base> base = factory.get("Derived");
Under the cover, the Factory will find the Base* associated to the "Derived" tag and invoke the clone method of the object. This will actually (here) create an object of runtime-type Derived.
We can verify this by using the typeid operator:
assert( typeid(base) == typeid(Derived) );
inmemory:
--------
type1 {
chartype a;
inttype b;
};
serialize(new type1());
serialized(ignore { and ,):
---------------------------
type1id,len{chartypeid,adata,inttypeid,bdata}
i guess, in an ideal serialization protocol, every non-primitive type need to be prefixed with typeid,len. Even if you serialize a single type that is not derived from anything, you would add a type id, because the other end has to know what type its getting (regardless of inheritance structure). So you have to mention derived class ids in the serialization, because logically they are different types. Correct me if i am wrong.