7

Let's say I have an interface and a class implementing it, like this:

class IPrinter
{
public:
    virtual void print(int i, int base = 10) = 0;
    virtual void print(char c) = 0;
    virtual void print(char *s) = 0;
    virtual void print(float f) = 0;
    virtual void print(double d) = 0;
    virtual ~IPrinter() = default;
private:
    ...
}

class Printer : public IPrinter
{
public:
    void print(int i, int base = 10) override {...}
    void print(char c) override {...}
    void print(char *s) override {...}
    void print(float f) override {...}
    void print(double d) override {...}
private:
    ...
}

And then I decide to add a simple decorator class, like this:

class SwitchablePrinter : public IPrinter
{
private:
    IPrinter& _printer;
    bool _enabled;
    ...
public:
    SwitchablePrinter(IPrinter& p) : 
        _printer(p), 
        _enabled(true) 
    {
    }

    void print_enable(bool on) { _enabled = on; }

    void print(int i, int base = 10) override
    {
        if (_enabled)
            _printer.print(i, base);
    }
    void print(char c) override
    {
        if (_enabled)
            _printer.print(c);
    }
    void print(char *s) override
    {
        if (_enabled)
            _printer.print(s);
    }
    void print(float f) override
    {
        if (_enabled)
            _printer.print(f);
    }
    void print(double d) override
    {
        if (_enabled)
            _printer.print(d);
    }
}

Now, all this is pretty simple and straightforward. The problem is that there is a lot of code duplication in the SwitchablePrinter implementation. I was wondering, that if there was a way to write a generic method 'print' for all overloaded methods in the base class, like this:

(pseudo-code)
void print({any args})
{
    if (_enabled)
        _printer.print({any args});
}

I think there may be a solution using templates, but I am not very experienced with using them and need advice.

m.s.
  • 16,063
  • 7
  • 53
  • 88
Ganil
  • 519
  • 5
  • 13

2 Answers2

4

Although there is no mechanism to override multiple member functions at once, you can simplify your task and reduce code duplication by providing a private variadic member function template that forwards the call to the proper overload of the wrapped _printer, like this:

private:
    template <class ... T>
    void print_impl(T ... vals) {
         if (_enabled)
             _printer.print(vals...);
         else
             cout << "disabled" << endl;
    }
public:
    void print(int i, int r) override {
        print_impl(i, r);
    }
    void print(float f) override {
        print_impl(f);
    }
    void print(double d) override {
        print_impl(d);
    }
    void print(char* s) override {
        print_impl(s);
    }
    void print(char c) override {
        print_impl(c);
    }

Demo.

This is only a slight improvement on the original, because the forwarding logic of print_impl is so simple. When the logic becomes more complex, payoff from sharing the code increases.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

The obvious thing to try is to replace the implementations in SwitchablePrinter with

template<typename T>
void print(T t) override
{
    if (_enabled)
        _printer.print(t);
}

(ignoring that there's a problem with the integer printing method.)

But this doesn't work, because member function templates cannot be virtual: Can a C++ class member function template be virtual?. (See the most upvoted answer, rather than the accepted one.) So your current implementation of SwitchablePrinter is the best, as far as I can see.

Community
  • 1
  • 1
gkt
  • 21
  • 1
  • 3