I'm reading the book by Alexandrescu, and I've run into the Acyclic Visitor pattern. I think that it's possible to get rid of the macross that calls AcceptImpl method of the BaseVisitable class.
Could you tell me, whether the following implementation bellow conforms the standard?
class BaseVisitor
{
public:
virtual ~BaseVisitor() {}
};
template <class SpecificVisitable>
class SpecificVisitor
{
public:
virtual void Visit(SpecificVisitable& t) = 0;
protected:
~SpecificVisitor() {}
};
template <class SpecificVisitable>
class BaseVisitable
{
public:
void Accept(BaseVisitor& visitor)
{
SpecificVisitor<SpecificVisitable>& specificVisitor = dynamic_cast<SpecificVisitor<SpecificVisitable>&>(visitor);
specificVisitor.Visit(static_cast<SpecificVisitable&>(*this));
}
protected:
~BaseVisitable() {}
};
class A : public BaseVisitable<A>
{
public:
void PrintA() { std::cout << "A\n"; }
};
class B : public BaseVisitable<B>
{
public:
void PrintB() { std::cout << "B\n"; }
};
class PrintVisitor final:
public BaseVisitor,
public SpecificVisitor<A>,
public SpecificVisitor<B>
{
public:
virtual void Visit(A& a) override
{
a.PrintA();
}
virtual void Visit(B& b) override
{
b.PrintB();
}
};
int main()
{
A a;
B b;
PrintVisitor visitor;
a.Accept(visitor);
b.Accept(visitor);
}
I agree with the commenters to the original post that state that a dynamic_cast to a reference will fail. You are not testing that situation, so your code will of course work just fine. But, in the general case, it's wrong.
I recommend that you instead rewrite BaseVisitable to instead cast to a pointer and check that pointer before dispatching on it. Something like
if (auto sv = dynamic_cast<SpecificVisitor<SpecificVisitable>*>(visitor))
sv->visit(*this)
Related
I have several disparate templated pure abstract classes. I derive from these to get a bunch of classes, and from there, I can use those to make a bunch of objects. I would like to put all of these objects into a container. However, they are all of different types. I am wondering how to accomplish this late-stage polymorphism.
Say this is my pre-existing code that I have right now:
#include <iostream>
template<typename T>
class A{
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B{
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
A_example first;
B_example second;
first.printNum();
second.printTwiceNum();
return 0;
}
With more classes, it could get pretty messy inside of main(). Ideally I could jut iterate over the container and call print() on each element. My first thought is to use a std::vector<unique_ptr<Base>>. This seems to work:
#include <iostream>
#include <vector> // new include
#include <memory> // new include
#include <utility> // new include
// new Base class here
class Base{
public:
virtual ~Base(){};
};
template<typename T>
class A : public Base{ // new inheritance here
public:
A() : m_num(1.0) {};
virtual ~A() {};
virtual void printNum() const = 0;
protected:
T m_num;
};
template<typename T>
class B : public Base{ // new inheritance here as well
public:
B() : m_num(2.0) {};
virtual ~B() {};
virtual void printTwiceNum() const = 0;
protected:
T m_num;
};
class A_example : public A<int>
{
public:
A_example() : A<int>() {};
void printNum() const { std::cout << m_num << "\n"; };
};
class B_example : public B<int>
{
public:
B_example() : B<int>() {};
void printTwiceNum() const { std::cout << 2*m_num << "\n"; };
};
int main(){
std::vector<std::unique_ptr<Base>> v;
v.emplace_back( new A_example() );
v.emplace_back( new B_example() );
//v[0]->printNum(); // nope
//v[1]->printTwiceNum(); // nope
return 0;
}
This is cool because I didn't have to change A_example or B_example, and all I changed in A and B was that I added : public Base. However, I have no idea how to call each elements print*** function. Is there any way to call the printNum() and printTwiceNum() functions, and for them to be automatically recognized?
The simplest approach is to just make a virtual function Base::print and have your derived classes implement it. But that's not always appropriate.
Another approach is to branch on dynamic_cast conversions. The premise there is that some functions are only available on some classes. But this can get hairy especially when using class templates, as you must handle all expected template parameters.
To generalize this, you can use interface classes. Let's say you have lots of different classes but only a small number of print variations. In that case, it may make sense to do this:
class PrintNumInterface {
public:
virtual void printNum() const = 0;
};
class PrintTwiceNumInterface {
public:
virtual void printTwiceNum() const = 0;
};
template<typename T> class A : public Base, public PrintNumInterface { ... };
template<typename T> class B : public Base, public PrintTwiceNumInterface { ... };
And now, no matter how many additional classes or template expansions you have to deal with, you only need to handle these interfaces:
for (auto& p : v)
{
if (PrintNumInterface* iface = dynamic_cast<PrintNumInterface*>(p.get())
iface->printNum();
else if (PrintTwiceNumInterface* iface = dynamic_cast<PrintTwiceNumInterface*>(p.get())
iface->printTwiceNum();
}
How to do multiple inheritance just for function?
must share data of the base class
no virtual function (assume that vtable is expensive)
avoid virtual inheritance
implementation must be able to reside in .cpp
c++14 is allowed
Here are similar questions :-
Multiple inheritance in diamond shape with functions only - use virtual inheritance. Virtual inheritance is generally bad and expensive.
multiple inheritance without virtual inheritance - focuses on syntax and compiling rather than programming technique.
Multilevel inheritance in c++ (CRTP) , CRTP and multilevel inheritance , Eliminate redundancy with CRTP and multiple inheritance (C++03) and Using CRTP with virtual inheritance - implementation must be in header
Here is a sample code (coliru demo) :-
class O{
protected: int database=0;
};
class A : public O{
public: void print(){
std::cout<<database<<std::endl;
}
};
class B : public O{
public: void set(int s){
database=s+1;
}
};
class AB : public O{
public: void print(){//duplicate
std::cout<<database<<std::endl;
}
public: void set(int s){//duplicate
database=s+1;
}
};
//AB ab; ab.set(1); ab.print(); // would print 2
Here is my attempt (wandbox demo). I abuse CRTP :( :-
class O{
public: int database=0;
};
template<class T>class OA{
public: void print(){
std::cout<<static_cast<T*>(this)->database<<std::endl;
}
};
template<class T>class OB{
public: void set(int s){
static_cast<T*>(this)->database=s+1;
}
};
class A :public O,public OA<A>{};
class B :public O,public OB<B>{};
class AB :public O,public OA<AB>,public OB<AB>{};
It works, but it looks inelegant.
Furthermore, implementation must be in header (because OA and OB are template classes).
Are there better approaches? Or is this the way to go?
Sorry if it is too newbie question or already asked. I am a C++ beginner.
Edit
Give extended example of using please.
In ECS, it would be useful in some cases :-
class O{
protected: EntityHandle e;
};
class ViewAsPhysic : public O{ //A
public: void setTransform(Transformation t){
Ptr<PhysicTransformComponent> g=e;
g->transform=t;
}
};
class ViewAsLight : public O{ //B
public: void setBrightness(int t){
Ptr<LightComponent> g=e;
g->clan=t;
}
};
class ViewAsLightBlock : public O{ //AB
//both functions
};
The problem here is that the database field is member of class O. So without virtual inheritance, A and B will have each their own copy of database. So you must find a way to force A and B to share same value. You could for example use a reference field initialized in a protected constructor:
#include <iostream>
class O{
int _db;
protected: int &database;
O(): database(_db) {};
O(int &db): database(db) {};
};
class A : public O{
public: void print(){
std::cout<<database<<std::endl;
}
A() {} // public default ctor
protected: A(int& db): O(db) {}; // protectect ctor
};
class B : public O{
public: void set(int s){
database=s+1;
}
B() {} // public default ctor
protected: B(int& db): O(db) {}; // protectect ctor
};
class AB : public A, public B {
int _db2;
public: AB(): A(_db2), B(_db2) {}; // initialize both references to same private var
};
int main() {
AB ab;
ab.set(1);
ab.print();
return 0;
}
displays as expected:
2
Above code uses no virtual inheritance, no virtual function and no templates, so method can safely implemented in cpp files. The class AB actually uses methods from its both parents and has still a coherent view on its underlying data. In fact it simulates an explicit virtual inheritance by building the common data in the most derived class and injecting in through protected constructors in its parents.
Something like this?
must share data of the base class - check
no virtual function (assume that vtable is expensive) - check
avoid virtual inheritance - check
implementation must be able to reside in .cpp- check
c++14 is allowed - check. c++11 used.
#include <iostream>
class O {
protected:
int database = 0;
};
/*
* the concept of implementing print for a base class
*/
template<class...Bases>
struct implements_print : Bases... {
void print() const {
std::cout << this->database << std::endl;
}
};
/*
* The concept of implementing set for a base class
*/
template<class...Bases>
struct implements_set : Bases... {
void set() {
++this->database;
}
};
struct B : implements_set<O> {
};
struct A : implements_print<O> {
};
struct AB : implements_set<implements_print<O>> {
};
int main() {
A a;
a.print();
B b;
b.set();
AB ab;
ab.set();
ab.print();
}
Another way, using composition and an access class to provide access to the protected member. This example shows how to defer the work on database to another compilation unit:
#include <iostream>
/*
* this stuff in cpp
*/
namespace implementation
{
void print(const int& database) {
std::cout << database << std::endl;
}
void set(int& database) {
++database;
}
}
/*
* this stuff in header
*/
struct OAccess;
class O {
private:
int database = 0;
friend OAccess;
};
struct OAccess {
template<class Host>
constexpr decltype(auto) database(Host &host) const { return (host.database); } // note: () makes reference
template<class Host>
constexpr decltype(auto) database(Host const &host) const { return (host.database); } // note: () makes reference
};
/*
* the concept of implementing print for a derived class
*/
template<class Host>
struct implements_print {
void print() const {
OAccess access;
implementation::print(access.database(self()));
}
private:
decltype(auto) self() const { return static_cast<Host const &>(*this); }
};
/*
* The concept of implementing set for a derived class
*/
template<class Host>
struct implements_set {
void set() {
OAccess access;
implementation::set(access.database(self()));
}
private:
decltype(auto) self() { return static_cast<Host &>(*this); }
};
template<template<class> class...Impls>
struct OImpl : Impls<OImpl<Impls...>> ..., O {
};
using B = OImpl<implements_set>;
using A = OImpl<implements_print>;
using AB = OImpl<implements_print, implements_set>;
int main() {
A a;
a.print();
B b;
b.set();
AB ab;
ab.set();
ab.print();
}
We start with defining the concepts of things that can print and things that can be set:
namespace util {
template<class Base, class Derived, class R=void>
using if_base = std::enable_if_t< std::is_base_of< std::decay_t<Base>, std::decay_t<Derived>>::value, R >;
struct stub {};
}
namespace concepts {
template<class Token>
void do_print(Token, util::stub const&)=delete;
template<class Token>
void do_set(Token, util::stub&, int)=delete;
struct has_print {
struct token { friend struct has_print; private: token(int){} };
template<class T>
friend util::if_base<has_print, T> print(T const& t) {
do_print(get_token(), t);
}
private: static token get_token() { return 0; }
};
struct has_set {
struct token { friend struct has_set; private: token(int){} };
template<class T>
friend util::if_base<has_set, T> set(T& t, int x) {
do_set(get_token(),t, x);
}
private: static token get_token() { return 0; }
};
}
We then declare O and the operations you can support on it:
namespace DB {
class O;
void do_print(::concepts::has_print::token, O const& o);
void do_set(::concepts::has_set::token, O& o, int);
class O{
protected: int database=0;
friend void do_print(::concepts::has_print::token, O const&);
friend void do_set(::concepts::has_set::token, O&, int);
};
class A : public O, public concepts::has_print {
};
class B : public O, public concepts::has_set {
};
class AB : public O, public concepts::has_print, concepts::has_set {
};
}
void DB::do_print(::concepts::has_print::token, O const& o ) { std::cout << o.database << std::endl; }
void DB::do_set(::concepts::has_set::token, O& o, int x) { o.database = x+1; }
The hard part of this is the access control.
I ensure it isn't possible to call do_set except through has_set::set.
That is what all those tokens are about. You can strip them out and their overhead if you are willing to just say "don't call the do_ functions" (and maybe give them another name, like private_impl_set).
Live example.
To start discussion.
class O
{
// no virtual destructor. So cant use polymorphic deletion
// like :
// O *o = new AB;
// delete o;
protected: int database=0;
};
class A : virtual public O{
public: void print(){
std::cout<<database<<std::endl;
}
};
class B : virtual public O{
public: void set(int s){
database=s+1;
}
};
class AB : protected A, protected B{}; // no vtable
void foo() {
AB ab;
ab.print(); // won't perform virtual call.
}
I'm looking for ways to avoid the "call super" code smell. This code smell is present when a subclass is required to invoke the super class's version of a virtual function when re-implementing that function.
class Base
{
public:
virtual void foo(){ ... }
}
class Derived : public Base
{
public:
virtual void foo(){ Base::foo();// required! ... }
}
If inheritance went only a single layer deep, I could use the template method
class Base
{
public:
void foo(){ ... ; foo_impl(); }
protected:
virtual void foo_impl(){}
}
class Derived : public Base
{
protected:
virtual void foo_impl(){ ... }
}
But if I need to subclass Derived, I'm back where I started.
I'm considering a registration approach.
class Base
{
public:
Base()
{
_registerCallback( [this](){ _baseFoo(); } );
}
void foo()
{
for( auto f : _callbacks )
f();
}
protected:
void registerCallback( std::function<void()> f )
{
_callbacks << f;
}
private:
void _baseFoo() { ... }
std::list< std::function<void()> > _callbacks;
}
class Derived : public Base
{
public:
Derived()
{
_registerCallback( [this](){ _derivedFoo(); } );
}
private:
virtual void _derivedFoo(){ ... }
}
Is there a more standard approach? Any problems with or improvements to this approach?
Use of
class Derived : public Base
{
public:
virtual void foo(){ Base::foo();// required! ... }
}
is the best approach IMO. I am not sure why you would consider that "code smell".
The potential for error is higher in the last approach you suggested.
It's easier to detect a missed call to Base::foo().
If all the classed derived from Base need to implement what Base::foo() does, it's better that the common code be in Base::foo(). The derived classes simply need to make the call.
For what it's worth, we use the pattern at my work a lot and it has proven to be robust over 20+ years of usage.
You can continue using template methods all the way down if you introduce new virtual member function on each level and override it on next one:
template <typename> struct tag {};
class Base
{
public:
void foo() { ... ; foo_impl(tag<Base>{}); }
protected:
virtual void foo_impl(tag<Base>) {}
};
class Derived1 : public Base
{
protected:
virtual void foo_impl(tag<Base>) override final { ... ; foo_impl(tag<Derived1>{}); }
virtual void foo_impl(tag<Derived1>) {}
};
class Derived2 : public Derived1
{
protected:
virtual void foo_impl(tag<Derived1>) override final { ... ; foo_impl(tag<Derived2>{}); }
virtual void foo_impl(tag<Derived2>) {}
};
class Derived3 : public Derived2
{
protected:
virtual void foo_impl(tag<Derived2>) override final { ... ; foo_impl(tag<Derived3>{}); }
virtual void foo_impl(tag<Derived3>) {}
};
If you dislike tag dispatch you can just give methods different names instead, perhaps something like foo_impl_N.
I consider all this overengineering.
chris mentioned a primary concern regards childs not calling their parent's corresponding member functions, this gives an idea about fixing that part:
#include <cassert>
class Base {
public:
void foo() {
foo_impl();
assert(base_foo_called && "call base class foo_impl");
}
protected:
virtual void foo_impl() { base_foo_called = true; }
private:
bool base_foo_called = false;
};
class DerivedFine : public Base {
protected:
void foo_impl() override {
Base::foo_impl();
}
};
class DerivedDerivedFine : public DerivedFine {
protected:
void foo_impl() override {
DerivedFine::foo_impl();
}
};
class DerivedDerivedNotFine : public DerivedFine {
protected:
void foo_impl() override {}
};
int main() {
DerivedFine foo;
foo.foo();
DerivedDerivedFine bar;
bar.foo();
DerivedDerivedNotFine baz;
baz.foo(); // this asserts
}
CRTP can solve everything.
For each foo method, you implement an empty non-virtual foo_before() that does nothing in your CRTP helper.
CRTP helper takes a derived and a base. Its virtual void foo() invokes static_cast<Derived*>(this)->foo_before() then Base::foo() then after_foo().
struct Base {
virtual void foo() { std::cout << "foo\n"; }
virtual ~Base() {};
};
template<class D, class B=Base>
struct foo_helper:B {
virtual void foo() {
static_cast<D*>(this)->before_foo();
this->B::foo();
static_cast<D*>(this)->after_foo();
}
private:
void before_foo() {}; void after_foo() {};
};
struct Derived1 : foo_helper<Derived1> {
void before_foo() { std::cout << "before1\n"; }
};
struct Derived2 : foo_helper<Derived2> {
void before_foo() { std::cout << "before2\n"; }
void after_foo() { std::cout << "after2\n"; }
};
struct DoubleDerived : foo_helper<DoubleDerived, Derived2> {
void after_foo() { std::cout << "even more after\n"; }
};
int main() {
std::cout << "---- Derived1\n";
Derived1 d1;
d1.foo();
std::cout << "---- Derived2\n";
Derived2 d2;
d2.foo();
std::cout << "---- DoubleDerived\n";
DoubleDerived dd;
dd.foo();
}
Live example.
Output:
---- Derived1
before1
foo
---- Derived2
before2
foo
after2
---- DoubleDerived
before2
foo
after2
even more after
Here's an idea inspired by this answer
The idea is to use the fact that constructors and destructors of a struct / class provides a sort of "pre/post function calling" mechanism that gets inherited. So instead of doing the pre/post function calls in the virtual method itself, we can use a functor and define the pre/post function call in the constructor / destructor. That way, functors that inherit from the base functor will inherit the pre/post function call.
Code
struct BasePrePostFunctor
{
BasePrePostFunctor()
{
printf("Base pre-func\n");
}
virtual void operator()()
{
printf("Base Main func\n");
}
~BasePrePostFunctor()
{
printf("Base post-func\n");
}
};
struct DerivedPrePostFunctor : BasePrePostFunctor
{
DerivedPrePostFunctor()
{
printf("Derived pre-func\n");
}
void operator()() override
{
printf("Derived main func\n");
}
~DerivedPrePostFunctor()
{
printf("Derived post-func\n");
}
};
class BaseClass
{
public:
virtual void virtual_func()
{
BasePrePostFunctor func;
func();
}
};
class DerivedClass : public BaseClass
{
public:
void virtual_func() override
{
DerivedPrePostFunctor func;
func();
}
};
int main(int argc, char** argv)
{
DerivedClass derived;
derived.virtual_func();
};
Output
Base pre-func
Derived pre-func
Derived main func
Derived post-func
Base post-func
I have the following code :
class A{};
class B: public A{};
class C: public A{};
class MyVisitor
{
public:
void visit(B*);
void visit(C*);
};
And then collection of A* objects, I want to achieve the following :
1)
MyVisitor visitor;
for(vector<A*>::iterator it = vec.begin(); it!= vec.end();it++)
visitor->visit(a);
2) Somehow determine at compile time, if A* points to derived object D,and give compiler error, if MyVisitor::visit(D*) function is not present
I know that 1) is achievable with some multimethods implementation, I guess I can find some implementations of multimethods for c++ . But is 2) somehow possible ?
You could use dynamic_cast like this (inside the body of your for loop) since the behavior should vary at run-time (according to the actual type of data).
ClassB* ba = dynamic_cast<ClassB*>(a);
if (ba)
visitor->visit(ba);
ClassC* ca = dynamic_cast<ClassC*>(a);
if (ca)
visitor->visit(ca);
Maybe your visit functions might be declared virtual (for your ClassD thing).
Otherwise organize your classes as a tree (not a forest) of classes, and have your topmost root class
class Topmost {
virtual int classnum() const;
and adopt the convention that each non-abstract class gives its unique classnum etc... Or have a metaclass mechanism (like e.g. Qt has)
You can try something like this.
#include <iostream>
class A
{
virtual void visit() = 0;
};
class B: private A
{
public:
void visit()
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
class C: private A
{
public:
void visit()
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
template <typename... Args>
class MyVisitor : public Args...
{
public:
template <typename T>
void visit(T* t)
{
t->visit();
}
};
int main()
{
MyVisitor<B, C> visitor;
B b;
B* bp = &b;
visitor.visit(bp);
return 0;
}
Live example
You may apply the visitor pattern completly:
class B;
class C;
class IVisitor
{
public:
void visit(B&) = 0;
void visit(C&) = 0;
};
class A
{
virtual ~A() = default;
virtual void accept(IVisitor& v) = 0;
};
class B: public A{ void accept(IVisitor& v) override { v.visit(*this); } };
class C: public A{ void accept(IVisitor& v) override { v.visit(*this); } };
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);
}