Refactoring tightly related classes when only one side can be changed

Please accept my apologies in advance for the somewhat lengthy question. This is the smallest stand-alone example I could come up with ... I'm sure there must be some obvious / nice / neat solution to solve this problem, but I don't see it at the moment.

Ok, here's the problem: imagine the following situation (nb. Compiled version of the code is available at http://goo.gl/dhRNex ). Let be

struct Thing1 {
public:
  void bar(class Implementation1 &i) {
    i.baz();
  }

  // ...various other methods like bar()
};

struct Thing2 {
public:
  void bar(class Implementation2 &i) {
    i.qux();
  }

  // ...various other methods like bar()
};

      

... Unfortunately, these classes are fixed, i.e. Cannot be changed / reorganized.

However, they are Implementation1

also Implementation2

changeable. These two classes have a lot of the same code, so it is natural to use common code in a common base class. However, the code depends on the type used Thing

, but there is no common base class for Thing1

and Thing2

, so it seems natural to use templates. So I worked out the following base class solution

template<class T, class S>
struct ImplementationBase {
public:
  S *self;

  void foo() {
    T thing;
    thing.bar(*self);
  }

  // ...lots more shared code like foo()
};

      

and specific implementations

struct Implementation1 : public ImplementationBase<class Thing1, class Implementation1> {
public:
  Implementation1() {
    self = this;
  }

  void baz() {
    std::cout << "Qux!" << std::endl;
  }
};

struct Implementation2 : public ImplementationBase<class Thing2, class Implementation2> {
public:
  Implementation2() {
    self = this;
  }

  void qux() {
    std::cout << "Qux!" << std::endl;
  }
};

      

Ideally, instead of self

in foo

should be used this

, but the problem is that it this

has a type ImplementationBase<class Thing1, class Implementation1>

but is required Implementation1

. Obviously, all this is quite a mess, and the classes Implementation

and Thing

too closely related, but I do not see an easy way out, not being able to reorganize classes Thing

. So finally my questions:

  • Is there a better alternative to using the trick self

    above?
  • Is there a design that better resolves this problem? (I have a feeling, I have, but that I will miss something obvious)

If you've made it this far, thank you so much for taking the time to read the whole story and my apologies again for this long-standing question.

+3


source to share


1 answer


You're already using CRTP so you don't need to:



template<class T, class S>
struct ImplementationBase {        
public:
  S* getThis() { return static_cast<S*>(this); }

  void foo() {
    T thing;
    thing.bar(*getThis());
  }

  // ...lots more shared code like foo()
};

      

+2


source







All Articles