When I use static polymorphism (CRTP), is there a nice way to give polymorphic methods their names?
template <class Derived>
struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Because, as far as I know, interface and implementation can't have the same name (as they would if they were virtual). And that's kinda awkward, if class hierarchy is deep.
Maybe there is some nice way to deal with it? Or maybe I'm just wrong?
My approach would be to avoid inheritance (however cute CRTP feels), and use aggregation instead. A class template provides the interface, and is in turn provided a delegate class with the implementation. It would look something like this:
template <class Delegate>
struct Interface
{
void do_something()
{
// ...
delegate.do_something();
// ...
}
Delegate delegate;
};
This has the disadvantage that it's more awkward to supply constructor arguments to the delegate object, but that's not too difficult to manage.
When the parent class doesn't have any special functionality (as in a typical abstract interface), I can't see a reason why you can't reuse the function name in the child class. It will hide the parent method, but that doesn't matter because you're statically telling the compiler which version you wish to use.
However in your case it appears that you want the parent to do some work before and after calling the virtual method (smells like Template Method Pattern). In this case, regardless of whether you use runtime (virtual) or compile time (CRTP) polymorphism, you'll need to call your interface and implementation methods by alternate names.
If foo is the interface/template method in the base, then do_foo or foo_impl seem like perfectly reasonable names for the implementation functions regardless of runtime or compile time polymorphism.
Related
I use LuaBridge to import a large framework of classes into a Lua-accessible framework. LuaBridge uses complex template functions that maintain a list of linkages back to methods and properties of each class. The Lua language itself is loosely typed, and it does not check to see if a method or property exists until you call it. My framework implements a ClassName method at every level that allows the Lua programs to know which class it is dealing with.
That's just background for my program. This is a C++ question. I would like to call a function that, in its broadest abstraction, looks something like this:
template <typename T>
do_something_in_lua(T * object); // LuaBridge will create a pointer to a T instance in Lua
and call it like this:
class foobase
{
public:
void notify_lua()
{ do_something_in_lua(this); }
};
class foo : public foobase
{
public:
int some_method();
};
foo x;
x.notify_lua();
My question is, is there a simple way for do_something_in_lua to use the maximally downcasted version of T? Either when I call it or in the templated function? Using dynamic_cast is difficult because I would have to maintain an explicit list of every possible subclass to find the right one. Even if it is adding a templated virtual function in foobase that returns the desired type of this, I would be interested in suggestions for an elegant solution.
I guess a broader version of my question would be, does modern C++ provide any tools for downcasting in template programming (e.g., in type_traits or the like) that I should be investigating?
Thanks to several helpful comments, the solution turns out to be a hybrid of CRTP and Double Dispatch. Here is a version of it based on my example above. I like the fact that it
requires no pure virtual functions
does not require templatizing the base class (for reasons specific to my code base)
If I ever need to add a new subclass, I just need to add it to the list in the std::variant, and better yet, the compiler will complain until I do so.
template <typename T>
void do_something_in_lua(T * object);
// every subclass of foobase must be listed here.
class foosub1;
class foosub2;
using foobase_typed_ptr = std::variant<foosub1*, foosub2*>;
class foobase
{
foobase_typed_ptr _typedptr;
public:
foobase(const foobase_typed_ptr &ptr) : _typedptr(ptr) {}
void notify_lua()
{
std::visit([](auto const &ptr)
{ do_something_in_lua(ptr); },
_typedptr);
}
};
class foosub1 : public foobase
{
public:
foosub1() : foobase(this) {}
int some_method1();
};
class foosub2 : public foobase
{
public:
foosub2() : foobase(this) {}
int some_method2();
};
// and to call it in code:
foosub2 x;
x.notify_lua(); // now Lua gets called with a foosub2* instead of a foobase*.
For example, I have a base class Event and I want to ensure that every class derived from Event has defined an enum class Type member, so that T::Type is a valid type for any class T derived from Event.
Even after reading your comment I still don't understand your real goal here. BUT to asnwer the specific question you asked:
All you have to do is use the type from the derived class and you'll get a compilation error if it doesn't exist. That's the simplest approach.
Another straightforward method that's slightly different is to use a policy class templated on the event class:
template <typename T>
struct EventType;
template <>
struct EventType<A>
{
typedef int Type;
};
As only templates can in any way recognize such a thing, there is no way to enforce such a restriction.
Still, your templates can use sfinae to enforce their constraints, like has type member named alpha and is derived from beta.
Before you go down that route though, be sure the effort is worth it.
I don't know of a convenient way to do that with an enum, but perhaps a simpler way to accomplish your goal might be the use of a pure virtual base class.
class Event
{
virtual int getType() = 0; // pure virtual function
};
class Circus : public Event
{
// Circus does not implement getType
};
int main()
{
Circus c; // compile-time error
}
I was not really sure how to formulate my question, but here is the puzzle I am trying to resolve:
if (config.a)
myObject = new Object<DummyInterface>();
else
myObject = new Object<RealInterface>();
so the task is to create a object with a dummy interface if it is specified in config, otherwise use real interface class.
How do I declare myObject then?
there are couple options, I could have Object class to derive from abstract class without templates: i.e.:
class Base
{
...
}
template <class T>
class Object : public Base
{
...
}
Then I could declare myObject as:
Base* myObject;
But here is the problem: what if my Object class declares a non virtual method:
template <class T>
class Object : public Base
{
public:
T getInterface() { return myInterface;}
private:
T myInterface;
}
I cannot call it like this:
myObject->getInterface()
and I cannot do dynamic cast, because I don't know the type until the runtime...
Any suggestions how to get around it? Maybe there is a another solution?
One way around is to use the visitor pattern. This way, your base class may implement a visit() method and your derived instances can override...
For example..
SomeComponent
{
template <typename T> // I'm being lazy here, but you should handle specific types
void handle(T& cInst)
{
// do something
}
};
class Base
{
public:
virtual void visit(SomeComponent& cComp) = 0;
};
template <class T>
class Object : public Base
{
public:
virtual void visit(SomeComponent& cComp)
{
cComp.handle(*this);
}
};
Now you can do this
SomeComponent c;
Base* obj = new Object<int>;
obj->visit(c);
And c will get the correct type.
if (config.a)
myObject = new Object<DummyInterface>();
else
myObject = new Object<RealInterface>();
This construction is incorrect in terms of the polymorphism.
Two template instantiations are two different classes. The best situation is when you have something like that:
template <class T> SomeClass: public SomeBaseClass
{
};
.........
SomeBaseClass* myObject;
But it brings you no profit.
The simplest and right solution is the virtual functions. The visitor pattern seems useful too.
I actually think that the visitor pattern would be misused here. Instead, this is a classic switch-on-types code smell that is best handled by polymorphism.
When you say "what if one derived class has an additional method to call", that is assuming a specific design. That is not a functional requirement. A functional requirement would be "what if one of the two objects created had to do behavior X during event Y". Why is this different? Because there are a number of ways to implement this that don't require more interface (though maybe more methods).
Let me show an example.
You have your factory
std::map<ConfigValue, Generator> objectFactory_;
That you've registered a bunch of generators for (probably in constructor of class)
RegisterGenerator(configValueA, DummyGenerator);
RegisterGenerator(configValueB, RealGenerator);
...
And at some point you want to create one of those objects.
shared_ptr<Base> GetConfigObject(ConfigFile config)
{
return objectFactory_[config.a]();
}
And then you want to use the object for handling an event, you can do
void ManagingClass::HandleEventA()
{
theBaseObjectReturned->HandleEventAThroughInterfaceObject(this);
}
Note how I passed a this pointer. This means if you have one object that doesn't want to do anything (like make that extra behavior call) that your managing class may provide, it doesn't need to use this.
Object<DummyInterface>::HandleEventAThroughInterfaceObject(ManagingClass *)
{
// just do dummy behavior
}
And then if you want to do something extra (call a new behavior) it can do it through that pointer in the RealInterface
Object<RealInterface>::HandleEventAThroughInterfaceObject(ManagingClass * that)
{
that->DoExtraBehavior();
// then dummy - or whatever order
// you could even call multiple methods as needed
}
That's the basic approach you should always take when dealing with polymorphism. You should never have two different code paths for different types except through calls to virtual dispatch. You should never have two different code blocks, one that calls methods A, B, and C and another that only calls A and D when dealing with a base object, depending on type. Instead, always make the derived objects do the work of figuring out what to do - because they know who they are. If you need to do stuff in the managing object, pass a this pointer for them to work with.
I read an answer some time back to a question regarding dynamic_cast. The dynamic_cast failed to work because the base class had no virtual methods. One of the answers said that deriving from classes with no virtual methods generally means a bad design. Is this correct? Even without taking advantage of polymorphism, I still can't see the wrongness in doing this.
It depends what we're talking about:
for Traits classes (no data) it's fine (std::unary_function comes to mind)
for private inheritance (used instead of composition to benefit from Empty Base Optimization) it's fine too
The problem comes when you starts treating such a Derived object polymorphically wrt this Base class. If you ever attain such a position, then it's definite code smell.
Note: Even when noted as fine above, you are still providing the ability to use the class polymorphically, and you thus expose yourself to subtle bugs.
Deriving from a class is always a valid option, for the sake of code reuse.
Sometimes, we are not looking for polymorphic behavior. That's OK - there's a reason we have that option. If this is the case, though, then consider using private inheritance instead - if your class isn't meant to be polymorphic, then there's no reason for anyone to try to use it polymorphically.
Here is an OK example, to factor behaviors into policies (note the protected destructor):
struct some_policy
{
// Some non-virtual interface here
protected:
~some_policy() { ... }
private:
// Some state here
};
struct some_class : some_policy, some_other_policy { ... };
Another Ok example, to avoid code bloat in templates. Note the protected destructor:
struct base_vector
{
// Put everything which doesn't depend
// on a template parameter here
protected:
~base_vector() { ... }
};
template <typename T>
struct vector : base_vector
{ ... };
Another example, called CRTP. Note the protected destructor:
template <typename Base>
struct some_concept
{
void do_something { static_cast<Base*>(this)->do_some_other_thing(); }
protected:
~some_concept() { ... }
};
struct some_class : some_concept<some_class> { ... };
Another example, called Empty Base Optimization. Not really inheritance per se, since it is more a trick to allow the compiler to reserve no space in some_class for the base class (which acts as a private member).
template <typename T>
struct some_state_which_can_be_empty { ... };
template <typename T>
struct some_class : private some_state_which_can_be_empty<T> { ... };
As a rule of thumb, classes you inherit from should have either virtual or protected destructor.
Inheritance without virtual methods in C++ is nothing more than a code reuse.
I can't think of inheritance without polymorphism.
Some classes in the C++ standard library have protected members (which are only meaningful to a derived class) but no virtual member functions. I.e., they're designed for derivation, without having virtuals. This proves that it must generally be bad design to derive from a class without virtuals.
Cheers & hth.,
I have an abstract base class
class IThingy
{
virtual void method1() = 0;
virtual void method2() = 0;
};
I want to say - "all classes providing a concrete instantiation must provide these static methods too"
I am tempted to do
class IThingy
{
virtual void method1() = 0;
virtual void method2() = 0;
static virtual IThingy Factory() = 0;
};
I know that doesnt compile, and anyway its not clear how to use it even if it did compile. And anyway I can just do
Concrete::Factory(); // concrete is implementation of ITHingy
without mentioning Factory in the base class at all.
But I feel there should be some way of expressing the contract I want the implementations to sign up to.
Is there a well known idiom for this? Or do I just put it in comments? Maybe I should not be trying to force this anyway
Edit: I could feel myself being vague as I typed the question. I just felt there should be some way to express it. Igor gives an elegant answer but in fact it shows that really it doesn't help. I still end up having to do
IThingy *p;
if(..)
p = new Cl1();
else if(..)
p = new Cl2();
else if(..)
p = new Cl3();
etc.
I guess reflective languages like c#, python or java could offer a better solution
The problem that you are having is partly to do with a slight violation a single responsibility principle. You were trying to enforce the object creation through the interface. The interface should instead be more pure and only contain methods that are integral to what the interface is supposed to do.
Instead, you can take the creation out of the interface (the desired virtual static method) and put it into a factory class.
Here is a simple factory implementation that forces a factory method on a derived class.
template <class TClass, class TInterface>
class Factory {
public:
static TInterface* Create(){return TClass::CreateInternal();}
};
struct IThingy {
virtual void Method1() = 0;
};
class Thingy :
public Factory<Thingy, IThingy>,
public IThingy {
//Note the private constructor, forces creation through a factory method
Thingy(){}
public:
virtual void Method1(){}
//Actual factory method that performs work.
static Thingy* CreateInternal() {return new Thingy();}
};
Usage:
//Thingy thingy; //error C2248: 'Thingy::Thingy' : cannot access private member declared in class 'Thingy'
IThingy* ithingy = Thingy::Create(); //OK
By derinving from Factory<TClass, TInterface>, the derived class is forced to have a CreateInternal method by the compiler. Not deifining it will result in an error like this:
error C2039: 'CreateInternal' : is not
a member of 'Thingy'
There is no sure way to prescribe such a contract in C++, as there is also no way to use this kind of polymorphism, since the line
Concrete::Factory()
is always a static compile-time thing, that is, you cannot write this line where Concrete would be a yet unknown client-provided class.
You can make clients implement this kind of "contract" by making it more convenient than not providing it. For example, you could use CRTP:
class IThingy {...};
template <class Derived>
class AThingy : public IThingy
{
public:
AThingy() { &Derived::Factory; } // this will fail if there is no Derived::Factory
};
and tell the clients to derived from AThingy<their_class_name> (you could enforce this with constructor visibility tweaking, but you cannot ensure the clients don't lie about their_class_name).
Or you could use the classic solution, create a separate hierarchy of factory classes and ask the clients to provide their ConcreteFactory object to your API.
Static methods cannot be made virtual (or abstract, for that matter) in C++.
To do what you're intending, you can have have an IThingy::factory method that returns a concrete instance, but you need to somehow provide a means for factory to create the instance. For instance, define a method signature like IThing* (thingy_constructor*)() and have a static call in IThingy that you can pass such a function to that defines how IThingy will construct the factory instance. Then, in a dependent library or class, you can call this method with an appropriate function that, in turn, nows how to properly construct an object implementing your interface.
Supposing you haven't had your factory 'initializer' called, you'd want to take appropriate action, such as throwing an exception.