2

I have a class FooBar that contains a member of type Foo. This type can be inherited from so that FooBar has variable behaviour. Foo contains multiple overloads for the accessor method bar.

class FooBar;

class Foo{
    friend class FooBar;

    virtual void bar(int barIn){ bar_ = barIn; }
    virtual void bar(int barIn, float barScale){ bar(int(barIn * barScale)); }
    virtual void bar(const Foo& barSource){ bar(barSource.bar_); }
    int bar(){ return bar_; }

    int bar_;
};

class FooBar{
public:
    void bar(int barIn){ foo_.bar(barIn); }
    void bar(int barIn, float barScale){ foo_.bar(barIn, barScale); }
    void bar(const Foo& barSource){ foo_.bar(barSource); }
    int bar(){ return foo_.bar(); }
private:
    Foo& foo_;
};

Looks ok so far, but I feel like all the definitions for the FooBar.bar accessor are kind of unnecessary. I know that the compiler inlines them, so there should be no overhead, but the methods all got the same name and are all overloads of each other.

Is there a way in C++ to "export" (I haven't found a better word) the accessor so calls to FooBar.bar are just redirected to FooBar.foo_.bar?

One idea I had was overriding the operator -> for FooBar, but the real case has multiple classes like Foo, so that would only work for one of them.

iFreilicht
  • 13,271
  • 9
  • 43
  • 74
  • Read about slicing in C++. Your FooBar class probably doesn't do what you want. (I don't believe there are any generic ways to do the sort of "proxy"ing you want.) – Mat May 03 '14 at 11:05
  • The member `Foo foo_` should be reference/pointer. Otherwise all of the `FooBar::bar` methods will simply call corresponding `Foo::bar` methods, they will not behave polymorphic for the derived classes of `Foo`. If you try to send the `foo_` to `FooBar` from outside, then sending a derived class object of 'Foo' will be sliced and you will face unexpected behavior and hard to find errors. See [this](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c) and [this](http://en.wikipedia.org/wiki/Object_slicing) – Rakib May 03 '14 at 11:11
  • @RakibulHasan oh I didn't think about that. In the real case, it is in a fact a `unique_ptr`. Answer gets edited right now. – iFreilicht May 03 '14 at 11:18

1 Answers1

4

You could write a real generic forwarder:

class FooBar
{
public:
    template<typename... Args>
    auto bar(Args&&... args) -> decltype(foo_.bar(std::forward<Args>(args)...))
    {
        return foo_.bar(std::forward<Args>(args)...);
    }

private:
    Foo& foo_;
};

(this requires C++11, with C++14 you could even leave out the ->decltype... part)

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180