0

I'm trying to make classes that follow a pattern, but trying to avoid using inheritance to solve the problem. But there is some common code that can be pulled into it's own class which can be reused. Like this:

class Common {
    public:
        int foo() {return 1;}
};

class A {
    public:
        // Expose Common's public methods
        int bar() {return 2;}
    private:
        Common common;
};

class B {
    public:
        // Expose Common's public methods
        int bar() {return 3;}
    private:
        Common common;
};

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

std::variant<A, B> variant = A{};
std::visit(overloaded {
        [](A a) { a.foo(); },
        [](B b) { b.foo(); },
}, variant);

Is there any way to achieve what I want without writing this biolerplate code?

int A::foo() { return common.foo(); } 
int B::foo() { return common.foo(); } 
GBlodgett
  • 12,704
  • 4
  • 31
  • 45
user3666471
  • 907
  • 11
  • 24
  • 2
    Why do you want to avoid inheritance? – Stephan Dollberg Feb 09 '19 at 22:04
  • 2
    if you don't use virtual methods inheritance has zero runtime overhead, so unless you have a good reason for avoiding inheritance, I suggest you use inheritance. – bolov Feb 09 '19 at 22:06
  • Yeah, I wanted to see if I could get away without inheritance, but looks like I have to use it – user3666471 Feb 10 '19 at 21:45
  • If you dislike _public_ inheritance because it is exposed to users as an "is-a relationship" then here is another option: You can choose _private_ inheritance and then type `public: using Common::foo;` in `A` and `B`. You can think of that private inheritance as an "is-implemented-in-terms-of relationship". – Julius Feb 11 '19 at 17:13

1 Answers1

0

What you are trying to implement is typically called a mixin. See What is a mixin, and why are they useful?.

In C++, you typically either do:

  • Inheritance (without dynamic dispatching)
  • CRTP

See Two different mixin patterns in C++. (mixin? CRTP?)

There are also other less glamorous solutions:

  • Making the common member variable public or equivalent (requires changes to users)
  • A macro, an #include or any sort of code generation that expands to whatever interface you need
Acorn
  • 24,970
  • 5
  • 40
  • 69