Reputation: 6425
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
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
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