javaLover
javaLover

Reputation: 6425

Encapsulate a function with another function that has the same set of parameters

I have a function that has a lot of parameters. (4-7 parameters)

For simplicity, this is an example:-

class B{
    friend class C;
    int f(int param1,float param2, structA a, structB b){
         //... some code ...
    }
    //.... other functions ....
};

Sometimes, I want to encapsulate it under another (more-public) function that has the same signature:-

class C{
    B* b;
    public: int g(int param1,float param2, structA a, structB b){
        return b->f(param1,param2,a,b);
    }
    //.... other functions ....
};

In my opinion, the above code is :-

Is there any C++ technique / magic / design-pattern to assist it?

In the real case, it happens mostly in edge-cases that composition is just a little more suitable than inheritance.

I feel that <...> might solve my problem, but it requires template from which I want to avoid.

Upvotes: 0

Views: 240

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275936

In a public header:

using f_sig = int(int param1,float param2, structA a, structB b);

class hidden;
class famous {
  hidden* pImpl
public:
  f_sig g;
};

In your .cpp:

class hidden {
  friend class famous;
  f_sig f;
};

Now, you cannot use this pattern to define what f or g does, but this does declair their signatures. And if your definition doesn't match the declaration you get an error.

int hidden::f(int param1,float param2, structA a, structB b) {
  std::cout << "f!";
}
int famous::g(int param1,float param2, structA a, structB b) {
  return pImpl->f(param1, param2, a, b);
}

type the signatures wrong above, and you'll get a compile-time error.

Upvotes: 1

Vittorio Romeo
Vittorio Romeo

Reputation: 93384

but it requires template from which I want to avoid.

That's, in my opinion, the wrong mindset to have. You should avoid templates if you have a very good reason to do so, otherwise you should embrace them - they are a core feature of the C++ language.

With a variadic template, you can create a perfect-forwarding wrapper as follows:

class C{
    B* b;
public: 

    template <typename... Ts>
    int g(Ts&&... xs){
        return b->f(std::forward<Ts>(xs)...);
    }

};

The above g function template will accept any number of arguments and call b->f by perfectly-forwarding them.

(Using std::forward allows your wrapper to properly retain the value category of the passed expressions when invoking the wrapper. In short, this means that no unnecessary copies/moves will be made and that references will be correctly passed as such.)

Upvotes: 1

Related Questions