I am trying to find a way to express a common base type for two objects that inherit a pair of similar interfaces.
See the code below : it is apparent that there should be a possible common base type for fb1 and fb2 (for example, something like IFizzBuzz).
Does anyone know if that is possible (without requiring to templates if possible :-)
Thanks !
#include <memory>
#include <iostream>
struct IFizz {
virtual void DoFizz() = 0;
};
struct IBuzz {
virtual void DoBuzz() = 0;
};
struct Fizz : public IFizz {
void DoFizz() override {
std::cout << "Fizz\n";
}
};
struct Buzz1 : public IBuzz {
void DoBuzz() override {
std::cout << "Buzz1\n";
}
};
struct Buzz2 : public IBuzz {
void DoBuzz() override {
std::cout << "Buzz2\n";
}
};
struct FizzBuzz1 : public Fizz, public Buzz1 {
};
struct FizzBuzz2 : public Fizz, public Buzz2 {
};
// Expected "Base type" of FizzBuzz1 and FizzBuzz2
struct IFizzBuzz : public IFizz, public IBuzz {
};
int main()
{
{
FizzBuzz1 fb1;
fb1.DoFizz();
fb1.DoBuzz();
}
{
FizzBuzz2 fb2;
fb2.DoFizz();
fb2.DoBuzz();
}
// {
// // The line below is not legit and does not compile
// std::unique_ptr<IFizzBuzz> ifb(new FizzBuzz1());
// ifb->DoFizz();
// ifb->DoBuzz();
// }
return 0;
}
There are 3 common base classes for FizzBuzz1 and FizzBuzz2
IFizz
IBuzz
Fizz
Without changing the definitions of those two, there is no way to have them also have IFizzBuzz as a base.
You can however have an class that derives IFizzBuzz and delegates to one of the two, e.g.
template <typename FizzBuzz>
struct Wrapper : IFizzBuzz
{
void DoFizz() final { fizzBuzz.DoFizz(); }
void DoBuzz() final { fizzBuzz.DoBuzz(); }
private:
FizzBuzz fizzBuzz;
}
This can then be used, e.g.
std::unique_ptr<IFizzBuzz> ifb = std::make_unique<Wrapper<FizzBuzz1>>();
ifb->DoFizz();
ifb->DoBuzz();
ifb = std::make_unique<Wrapper<FizzBuzz2>>();
ifb->DoFizz();
ifb->DoBuzz();
Related
I have the following situation (live code : https://gcc.godbolt.org/z/d8jG9bs9a):
#include <iostream>
#include <type_traits>
#define ENBALE true // to enable disable test solutions
enum struct Type : unsigned { base = 0, child1, child2, child3 /* so on*/ };
// CRTP Base
template<typename Child> struct Base {
void doSomething() { static_cast<Child*>(this)->doSomething_Impl(); }
private:
Base() = default;
friend Child;
};
struct Child1 : public Base<Child1> {
void doSomething_Impl() { std::cout << "Child1 implementation\n"; }
};
struct Child2 : public Base<Child2> {
void doSomething_Impl() { std::cout << "Child2 implementation\n"; }
};
struct Child3 : public Base<Child3> {
void doSomething_Impl() { std::cout << "Child3 implementation\n"; }
};
// ... so on
class SomeLogicClass
{
Type mClassId{ Type::base };
Child1 mChild1;
Child2 mChild2;
Child3 mChild3;
public:
Type getId() const { return mClassId; }
void setId(Type id) { mClassId = id; } // run time depended!
#if ENBALE // Solution 1 : simple case
/*what in C++11?*/ getInstance()
{
switch (mClassId)
{
case Type::child1: return mChild1;
case Type::child2: return mChild2;
case Type::child3: return mChild3;
default: // error case!
break;
}
}
#elif !ENBALE // Solution 2 : SFINAE
template<Type ID>
auto getInstance() -> typename std::enable_if<ID == Type::child1, Child1&>::type { return mChild1; }
template<Type ID>
auto getInstance() -> typename std::enable_if<ID == Type::child2, Child2&>::type { return mChild2; }
template<Type ID>
auto getInstance() -> typename std::enable_if<ID == Type::child3, Child3&>::type { return mChild3; }
#endif
};
void test(SomeLogicClass& ob, Type id)
{
ob.setId(id);
#if ENBALE // Solution 1
auto& childInstance = ob.getInstance();
#elif !ENBALE // Solution 2
auto& childInstance = ob.getInstance<ob.getId()>();
#endif
childInstance.doSomething(); // calls the corresponding implementations!
}
int main()
{
SomeLogicClass ob;
test(ob, Type::child1);
test(ob, Type::child2);
test(ob, Type::child3);
}
The problem is that the child class selection (to which the doSomething_Impl() must be called), should be taken place by deciding upon a run time variable mClassId of the SomeLogicClass.
The only two possible solutions I can think of are a normal switch case and SFINAE the member functions, as described in the above minimal example. As noted in the comments in the above code, both can't get work, for the reasons
Solution 1: the member function must have a unique return type
Solution 2: SFINAE required a compile time expression to decide which overload to be chosen.
Update
The std::variant(as mentioned by #lorro) would be the easiest solution here. However, require C++17 support.
However, I would like to know if we got some way around which works under the compiler flag c++11?
Note: I am working with a code-base, where external libs such as boost, can not be used, and the CRTP class structure is mostly untouchable.
Since you are restricted to C++11 and are not allowed to use external libraries such as boost::variant, an alternative would be to reverse the logic: Do not attempt to return the child type but instead pass in the operation to perform on the child. Your example could become this (godbolt):
#include <iostream>
#include <type_traits>
enum struct Type : unsigned { base = 0, child1, child2, child3 /* so on*/ };
// CRTP Base
template<typename Child> struct Base {
void doSomething() { static_cast<Child*>(this)->doSomething_Impl(); }
private:
Base() = default;
friend Child;
};
struct Child1 : public Base<Child1> {
void doSomething_Impl() { std::cout << "Child1 implementation\n"; }
};
struct Child2 : public Base<Child2> {
void doSomething_Impl() { std::cout << "Child2 implementation\n"; }
};
struct Child3 : public Base<Child3> {
void doSomething_Impl() { std::cout << "Child3 implementation\n"; }
};
// ... so on
class SomeLogicClass
{
Type mClassId{ Type::base };
Child1 mChild1;
Child2 mChild2;
Child3 mChild3;
// ... child3 so on!
public:
Type getId() const { return mClassId; }
void setId(Type id) { mClassId = id; } // run time depended!
template <class Func>
void apply(Func func)
{
switch (mClassId){
case Type::child1: func(mChild1); break;
case Type::child2: func(mChild2); break;
case Type::child3: func(mChild3); break;
default: // error case!
break;
}
}
};
struct DoSomethingCaller
{
template <class T>
void operator()(T & childInstance){
childInstance.doSomething();
}
};
void test(SomeLogicClass& ob, Type id)
{
ob.setId(id);
ob.apply(DoSomethingCaller{});
// Starting with C++14, you can also simply write:
//ob.apply([](auto & childInstance){ childInstance.doSomething(); });
}
int main()
{
SomeLogicClass ob;
test(ob, Type::child1);
test(ob, Type::child2);
test(ob, Type::child3);
}
Notice how the new function apply() replaces your getInstance(). But instead of attempting to return the child type, it accepts some generic operation that it applies to the correct child. The functor passed in needs to cope (i.e. compile) with all possible child types. Since all of them have a doSomething() method, you can simply use a templated functor (DoSomethingCaller). Before C++14, unfortunately, it cannot simply be a polymorphic lambda but needs to be a proper struct (DoSomethingCaller) outside of the function.
If you care to do so, you can also restrict DoSomethingCaller to the CRTP base class Base<T>:
struct DoSomethingCaller
{
template <class T>
void operator()(Base<T> & childInstance){
childInstance.doSomething();
}
};
which might make it a bit more readable.
Depending on how strict the "no external libraries" restriction is, maybe only boost is not allowed but a single external header (that can be simply included in the code base as any other header file) would be possible? If yes, you might want to also have a look at variant-lite. It aims to be a C++98/C++11 compatible replacement for std::variant.
I recognize here the Bridge pattern in your CRTP code base, although done badly in my opinion. But anyway, if you can't touch that code then you should implement a second bridge code. Fortunately, with templates this won't be that hard.
Here is the code (godbold):
#include <iostream>
enum struct Type : unsigned { base = 0, child1, child2, child3 /* so on*/ };
// CRTP Base
template<typename Child> struct Base {
void doSomething() { static_cast<Child*>(this)->doSomething_Impl(); }
private:
Base() = default;
friend Child;
};
struct Child1 : public Base<Child1> {
void doSomething_Impl() { std::cout << "Child1 implementation\n"; }
};
struct Child2 : public Base<Child2> {
void doSomething_Impl() { std::cout << "Child2 implementation\n"; }
};
struct Child3 : public Base<Child3> {
void doSomething_Impl() { std::cout << "Child3 implementation\n"; }
};
// ... so on
class CommonInterface {
public:
virtual void doSomething() = 0;
};
template<class Child>
class ChildCaller : public CommonInterface {
private:
Child child;
public:
virtual void doSomething() {
child.doSomething_Impl();
}
};
class SomeLogicClass
{
Type mClassId{ Type::base };
ChildCaller<Child1> mChild1;
ChildCaller<Child2> mChild2;
ChildCaller<Child3> mChild3;
CommonInterface* currentChild;
public:
Type getId() const { return mClassId; }
void setId(Type id) {
mClassId = id;
switch(id) {
case Type::child1:
currentChild = &mChild1;
break;
case Type::child2:
currentChild = &mChild2;
break;
case Type::child3:
currentChild = &mChild3;
break;
default:
currentChild = nullptr; // or anything you want
}
}
void doSomething() {
currentChild->doSomething();
}
};
void test(SomeLogicClass& ob, Type id)
{
ob.setId(id);
ob.doSomething(); // calls the corresponding implementations!
}
int main() {
SomeLogicClass ob;
test(ob, Type::child1);
test(ob, Type::child2);
test(ob, Type::child3);
}
I omitted error checking here and there, so the code is more readable.
It is not clear if you want one element or one of each.
If you need one of each, SomeLogicClass should have a std::tuple<Class1, Class2, Class3>. This stores 'one of each', also provides std::get<>(), which returns element i. Thus, getInstance() can essentially delegate to std::get<ID>().
If you need one element of either type, SomeLogicClass should have a std::variant<Class1, Class2, Class3>. This stores the kind of the active element and the element itself. You can either use std::get<>() for it, or - better - you might visit via std::visit().
#include <iostream>
class Base {
public:
int a;
Base() : a(0) {};
};
class Inherited1 : public Base {
public:
void add() {
a++;
}
};
class Inherited2 : public Base {
public:
void sub() {
a--;
}
};
class Combined : public Inherited1, public Inherited2 {
//public:
// int& a;
//
// Combined() : a(Inherited1::a) {};
};
int main() {
Combined obj;
obj.add();
obj.add();
obj.sub();
std::cout << dynamic_cast<Inherited1*>(&obj)->a << ' '; // -> 2
std::cout << dynamic_cast<Inherited2*>(&obj)->a; // -> -1
return 0;
}
I want to somehow force add() method in Combined class to use the same variable as sub() method without changing Base, Inherited1 or Inherited2 classes, so my program would print out "1 1".
Is it even possible in that example?
I'm curious because I'm trying to create something like std::iostream, just for fun.
Let say I've this code with a EnvelopeMultiPoints class template:
#include <iostream>
#include <vector>
class EnvelopeMultiPointsBase
{
// base
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
void Process() {
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch> { };
template<typename T>
unsigned int EnvelopeMultiPoints<T>::mNumPoints = 5;
class Container
{
public:
EnvelopeMultiPointsBase *pAssociatedEnvelope;
Container(EnvelopeMultiPointsBase *associatedEnvelope) : pAssociatedEnvelope(associatedEnvelope) { }
~Container() { }
void Process();
private:
};
int main()
{
EnvelopeMultiPoints<Pitch> pitch;
Container container(&pitch);
container.pAssociatedEnvelope->Process();
}
And I want to pass to the Container any kind of "EnvelopeMultiPoints" types (a generic "pointer"), so later I can access to its own method (in my case, Process()).
Does it means that also Container must be templated? (which is huge in my real scenario; lot of works to transform all of its methods in template, translate header/cpp, and such).
Or is there a trick that I'm missing?
In few words: let say that I want to pass to Container EnvelopeMultiPoints<Pitch>, and than execute Process(). Later, I want to pass EnvelopeMultiPoints<Volume> instead, and than execute Process(). And so on. Is there a way to do this without converting also Container to a template?
The technique you need is called dynamic polymorphism
that is implemented in C++ by virtual functions.
Illustrating using your code:
class EnvelopeMultiPointsBase
{
public:
// Abstract base, no actual implementation
virtual void Process() = 0;
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
// Some specific implementation.
virtual void Process() override
{
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch>
{
};
To call the Process function of the base class, you have to define it in the base class. You can move the implementation to templated child classes:
class EnvelopeMultiPointsBase
{
private:
virtual void ProcessImpl() = 0;
public:
void Process() {
//potential common code...
ProcessImpl();
//more potential common code...
}
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
private:
void ProcessImpl() {
std::cout << "process" << std::endl;
}
};
Consider the below code, EventGeneratorBase is a helper class intended to provide the actual implementation for AddEventHandler() and I would like to use that implementation in the class RemoteControl instead of explicity defining it. I know it's not possible to instantiate RemoteControl without defining the method but is there a shortcut or an easy way to avoid manually defining the methods.
Note: The code in it's present form doesn't compile because RemoteControl can't be instantiated.
#include <iostream>
#include <vector>
#include <memory>
template<class TEventHandler> struct IEventGenerator {
virtual ~IEventGenerator() = default;
virtual void AddEventHandler(std::weak_ptr<TEventHandler> eventHandler) = 0;
};
template <class TEvents> struct EventGeneratorBase : IEventGenerator<TEvents> {
void AddEventHandler(std::weak_ptr<TEvents> target) {
_eventHandlers.push_back(target);
}
std::vector<std::weak_ptr<TEvents>> GetEventHandlers() {
return _eventHandlers;
}
private:
std::vector<std::weak_ptr<TEvents>> _eventHandlers;
};
struct IControlEvents {
virtual ~IControlEvents() = default;
virtual void PowerOn() = 0;
virtual void PowerOff() = 0;
};
struct IRemoteControl : IEventGenerator<IControlEvents> {
virtual ~IRemoteControl() = default;
virtual void Toggle() = 0;
};
struct RemoteControl : IRemoteControl, EventGeneratorBase<IControlEvents> {
// I don't want to define AddEventHandler() in this class and
// would like to inherit the implementation from EventGeneratorBase
void Toggle() {
for (auto tref : GetEventHandlers()) {
auto t = tref.lock();
if (t) {
t->PowerOn();
t->PowerOff();
}
}
}
};
struct Light : IControlEvents {
Light(std::string color) : _color(color) { }
void PowerOn() {
std::cout << _color << "::Light ON!" << std::endl;
}
void PowerOff() {
std::cout << _color << "::Light OFF!" << std::endl;
}
private:
std::string _color;
};
int main() {
std::shared_ptr<IRemoteControl> remote(new RemoteControl); // ERROR: Can't instantiate
std::shared_ptr<IControlEvents> light1(new Light("GREEN"));
std::shared_ptr<IControlEvents> light2(new Light("RED"));
remote->AddEventHandler(light1);
remote->AddEventHandler(light2);
remote->Toggle();
return 0;
}
Your problem is that you have two distinct sub-objects of type IEventGenerator<IControlEvents> within your RemoteControl object. One via EventGeneratorBase<IControlEvents> and one via IRemoteControl.
There are two ways to prevent you from having two distinct subobjects. The first is to inherit virtually from IEventGenerator<TEventHandler> in both spots. This has a modest run-time cost. Simply add virtual before every case of inheritance from IEventGenerator<?> and you are done.
A second method is to note that EventGeneratorBase is intended to help with implementing IEventGenerator.
template<class T> struct tag{using type=T;};
template<class Tag> using type_t=typename Tag::type;
template<class TEventHandler>
tag<TEventHandler> get_event_handler_type(
IEventGenerator<TEventHandler> const*
) { return {}; }
template<class X>
using event_handler_type = type_t< decltype( get_event_handler_type( (X*)nullptr ) ) >;
template <class Base, class TEvents = event_handler_type<Base>>
struct EventGeneratorHelper :
Base
{
void AddEventHandler(std::weak_ptr<TEvents> target) override {
_eventHandlers.push_back(target);
}
std::vector<std::weak_ptr<TEvents>> GetEventHandlers() {
return _eventHandlers;
}
private:
std::vector<std::weak_ptr<TEvents>> _eventHandlers;
};
now, go down to here:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
and change how we inherit. We now interpose EventGeneratorHelper between us and IRemoteControl, so they now share the same common IEventGenerator.
This removes the need for virtual inheritance, but does up your compile time, and can cause some executable code bloat.
We can go a step further. Add this to EventGeneratorHelper:
template<class Action>
void FireEvents( Action&& action ) const {
for (auto tref : GetEventHandlers()) {
auto t = tref.lock();
if (t) {
action(t);
}
}
}
which reduces RemoteControl to:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
void Toggle() {
this->FireEvents([](std::shared_ptr<IRemoteControl> const& ptr){
t->PowerOn();
t->PowerOff();
});
}
};
which I think is nice -- requiring clients to know the right way of iterating seems silly.
You have a problem in your inheritance hierarchy.
template <class TEvents> struct EventGeneratorBase :IEventGenerator<TEvents> {
[...]
};
struct IRemoteControl : IEventGenerator<IControlEvents> {
[...]
};
struct RemoteControl : IRemoteControl, EventGeneratorBase<IControlEvents> {
[...]
};
This is not doing what you might expect. Instead, your class RemoteControl inherits twice from IEventGenerator, once from IRemoteControl and once from EventGeneratorBase.
Edit: Per some comments, by simple I mean a) less code, b) easy to maintain, and c) hard to get wrong.
Edit #2: Also, using containment instead of private inheritance is not objectionable if it does indeed simplify the implementation of InterfaceImpl.
Currently, the only way I know to do this is to have the implementer define the abstract method and delegate the call to the target base type's method. Example:
#include <iostream>
#include <memory>
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
class MethodOneImpl
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
class MethodTwoImpl
{
public:
void myFunc(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
virtual void method1() { MethodOneImpl::method1(); }
virtual void method2(int x) { MethodTwoImpl::myFunc(x); }
};
int main()
{
std::unique_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf->method2(0);
// This should be disallowed!
// std::unique_ptr<MethodOneImpl> moi;
// moi.reset(new InterfaceImpl);
}
At first, I thought that perhaps this might solve the problem:
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
using MethodOneImpl::method1;
// Obviously this wouldn't work as the method names don't match.
//using MethodTwoImpl::???
};
The first using statement will make both MethodOneImpl::method1 methods be public, but it actually doesn't fulfill the contract with Interface, and it modifies the accessibility of MethodOneImpl::method1(int). And obviously we couldn't use this solution with method2 as the names don't match up.
FWIW, I have what I think is a solution, but it is not part of the standard at all (in other words it won't compile). I was thinking of making a proposal to the C++ committee; if anyone has any advice, I'd appreciate any comments below (but please dont' submit the advice as an answer).
An other option (at least if using MS VC++) is to use virtual inheritance:
struct MyInterface
{
virtual void Method1() = 0;
virtual void Method2() = 0;
};
class Method1Impl : public virtual MyInterface
{
virtual void Method1() { _tprintf( _T("Method1\n") ); }
};
class Method2Impl : public virtual MyInterface
{
virtual void Method2() { _tprintf( _T("Method2\n") ); }
};
class InterfaceImpl : public virtual MyInterface,
private Method1Impl,
private Method2Impl
{
};
void TestWeirdInterfaceImpl()
{
MyInterface* pItf = new InterfaceImpl();
pItf->Method1();
pItf->Method2();
}
While this seems to work and satisfy what you are looking for (asside from C4250 warning that you will have to suppress with a #pragma), this wouldn't be my approach. (I believe virtual inheritance is still not something that supported across all compilers, but I could be wrong).
I would probably go with containment and once boilerplate code is identifier, wrap it into some kind of macro map (similar to maps in ATL or MFC) that would make it really, really difficult to ever screw it up.
So this would be my macro approach:
struct MyInterface
{
virtual float Method1( int x ) = 0;
virtual int Method2( float a, float b ) = 0;
virtual void Method3( const TCHAR* sz ) = 0;
};
class Method1Impl
{
public:
float Method1( int x ) {
_tprintf( _T("Method1: %d\n"), x ); return 5.0;
}
};
class Method2and3Impl
{
public:
int Method2( float a, float b ) {
_tprintf( _T("Method2: %f, %f\n"), a, b ); return 666;
}
void Method3( const TCHAR* sz ) {
_tprintf( _T("Method3: %s"), sz );
}
};
#define DECLARE_METHOD0( MethodName, Obj, R ) \
virtual R MethodName() { return Obj.MethodName(); }
#define DECLARE_METHOD1( MethodName, Obj, R, A1 ) \
virtual R MethodName( A1 a1 ) { return Obj.MethodName( a1 ); }
#define DECLARE_METHOD2( MethodName, Obj, R, A1, A2 ) \
virtual R MethodName( A1 a1, A2 a2 ) { return Obj.MethodName( a1, a2 ); }
class InterfaceImpl : public MyInterface
{
public:
DECLARE_METHOD1( Method1, m_method1Impl, float, int );
DECLARE_METHOD2( Method2, m_method2and3Impl, int, float, float );
DECLARE_METHOD1( Method3, m_method2and3Impl, void, const TCHAR* );
private:
Method1Impl m_method1Impl;
Method2and3Impl m_method2and3Impl;
};
void TestWeirdInterfaceImpl()
{
MyInterface* pItf = new InterfaceImpl();
pItf->Method1( 86 );
pItf->Method2( 42.0, 24.0 );
pItf->Method3( _T("hi") );
}
Until C++ gods grace us with variadic macros, you'll have to declare one for each number of parameters you have. Also if you used multiple inheritance, potentially you wouldn't need the second "Obj" param, but as I've said before, I'd avoid multiple inheritance if there's another solution, which in this case is one extra param.
Yet a third option could be something that authors of Pragmatic Programmer seem to advocate a lot. If you have a ton of cookie cutter code that you don't want to repeat because, as you pointed out, it introduces human error. Define your own language and write a code generator script (python, perl...) to auto-create the actual code. In this case you could almost point at an interface, and have the script write the text out for you. I haven't tried doing this kind of thing myself, but lately have been wanting to use it somewhere just to see and evaluate the outcome.
This is sort of ugly and may bloat the executable size, but what about
#include <iostream>
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
template<typename T>
class MethodOneImpl : public T
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
template<typename T>
class MethodTwoImpl : public T
{
public:
void method2(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
class InterfaceImpl : public MethodTwoImpl<MethodOneImpl<Interface> >
{
};
int main()
{
InterfaceImpl impl;
impl.method1();
impl.method2(0);
}
class AbsInterface
{
// this is a simple interface class.
public:
virtual void Method1() = 0;
virtual void Method2() = 0;
};
class Functor1
{
public:
void operator () ()
{
printf("This Is Void Functor1");
}
};
class Functor2
{
public:
void operator () ()
{
printf("This Is void Functor2");
}
};
template <class T1, class T2>
class DerivedTemplateClass : public AbsInterface
{
public:
virtual void Method1() { T1()(); }
virtual void Method2() { T2()(); }
};
void main()
{
DerivedTemplateClass<Stratege1, Stratege2> instance;
instance.Method1();
instance.Method2();
}
as you can see, I used Functor.
You could work with template and functor.
It seems impossible to bring MethodOneImpl / MethodTwoImpl into the scope of Interface without having them inherit from Interface because they will not fill the Virtual Table if they don't. C++ misses something like the keyword implements from other languages.
So you are stuck with the virtual inheritence thing unless realize/accept that what you are looking for is just a bridge pattern, which does not satisfy requirement a) (you shall write more code), midly b) (code not necessarly difficult to maintain) and may satisfy c).
Here (another) possible solution (with only method though to reduce bloat)
class Interface
{ public:
virtual void method1() {return impl_->method1();}
private:
Interface() {}
protected:
struct Impl {
virtual void method1() = 0; };
std::shared_ptr<Impl> impl_;
Interface(const std::shared_ptr<Impl> &impl) : impl_(impl) {}
};
class InterfaceImpl : public Interface
{
struct Impl : public Interface::Impl {
void method1() { std::cout << "InterfaceImpl::method1() " << std::endl; } } ;
public:
InterfaceImpl() : Interface(std::shared_ptr<Impl> (new Impl)) {}
};
template <class T>
class GenericInterfaceImpl : public Interface {
struct Impl : public Interface::Impl {
Impl( T &t) : t_(t) {}
void method1() { t_.method1() ; }
T t_; };
public:
GenericInterfaceImpl() : Interface(std::shared_ptr<Impl> (new Impl(T()))) {}
};
struct AMethod1Impl {
void method1() { std::cout << "AMethod1Impl::method1() " << std::endl; } } ;
struct AnotherMethod1Impl_not_working {
void method1_not_present() { std::cout << "AnotherMethod1Impl_not_working ::method1_not_present() " << std::endl; } } ;
int main() {
// compilation of next line would fail
// (lame attempt to simulate ompilation fail when pure function not implemented)
// Interface inf;
std::unique_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf.reset(new GenericInterfaceImpl<AMethod1Impl>() );
inf->method1();
// compilation of next line would fail
// inf.reset(new GenericInterfaceImpl<AnotherMethod1Impl_not_working>() );
}
Does this serve your purpose?
It maintains the interface relationship and gives you maintainable code without having any consideration of client code.
Separating each method in functionoid and giving you the power to control the prototype of each method of the different base class.
#include <iostream>
#include <memory>
using namespace std;
//No Control over this.
class MethodOneImpl
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
class MethodTwoImpl
{
public:
void myFunc(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
//*************************//
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
//This is what i would do. //
class BaseFuncType
{
//no pure virtual
void Call()
{
throw "error";
}
void Call(int x)
{
throw "error";
}
};
class Method1: public BaseFuncType
{
auto_ptr<MethodOneImpl> MethodPtr;
public:
Method1()
{
MethodPtr.reset(new MethodOneImpl());
}
virtual int Call()
{
MethodPtr->method1();
}
};
class Method2: public BaseFuncType
{
auto_ptr<MethodTwoImpl> MethodPtr;
public:
Method2()
{
MethodPtr.reset(new MethodTwoImpl());
}
virtual int Call(int x)
{
MethodPtr->myFunc(x);
}
};
template <class T1>
class MethodFactory
{
private:
T1 methodObj;
public:
void CallMethod()
{
methodObj.Call();
}
void CallMethod(int x)
{
methodObj.Call(x);
}
};
class InterfaceImpl : public Interface
{
auto_ptr<MethodFactory> factory;
public:
virtual void method1()
{
factory.reset(new MethodFactory<Method1>());
factory->CallMethod();
}
virtual void method2(int x)
{
factory.reset(new MethodFactory<Method2>());
factory->CallMethod(x);
}
};
int main()
{
auto_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf->method2(10);
// This should be disallowed!
// std::unique_ptr<MethodOneImpl> moi;
// moi.reset(new InterfaceImpl);
}