5

I have a pair of overloaded functions:

void func(const std::string& str, int a, char ch, double d) { // piece of code A sendMsg(str, a, ch, d); // piece of code B } void func(int a, char ch, double d) { // piece of code A sendMsg(a, ch, d); // piece of code B } 

piece of code A and piece of code B are exactly the same, the only difference is the parameter of sendMsg.

Is there some way to avoid the code duplication?

8
  • What does sendMsg look like? Commented Aug 4, 2021 at 8:10
  • @mfnx It doesn't matter, no? sendMsg is a library function, which does some socket job. I can't change it anyway. Commented Aug 4, 2021 at 8:11
  • 3
    I didn't understand the question. Why can't we move A and B to its own functions? Anyone please explain. Commented Aug 4, 2021 at 8:25
  • 2
    @Yves thats the problem with asking how to avoid code without showing the code ;) No worries, I guess its a general difficulty with this kind of questions Commented Aug 4, 2021 at 8:33
  • 1
    IMO question is stripped from important details. This responses to answers not suitable for my case is best prove of that. Commented Aug 4, 2021 at 12:15

4 Answers 4

15

template may be a possibility:

template <typename ... Ts> auto func(const Ts&... args) -> decltype(sendMsg(args...), void()) // SFINAE to only allow correct arguments { // piece of code A sendMsg(args...); // piece of code B } 

but moving // piece of code A in its own function would probably be my choice.

Sign up to request clarification or add additional context in comments.

Comments

8

You would have to do something like

void codeA() { // ... } void codeB() { // ... } void func(const std::string& str, int a, char ch, double d) { codeA(); sendMsg(str, a, ch, d); codeB(); } void func(int a, char ch, double d) { codeA(); sendMsg(a, ch, d); codeB(); } 

1 Comment

Well, add two functions are not suitable for my case.
6

Another idea would be to give a default value to str:

void func(int a, char ch, double d, const std::string& str = "") { // piece of code A if (str.empty()) sendMsg(a, ch, d); else sendMsg(str, a, ch, d); // piece of code B } 

3 Comments

it can be const std::string& also with a default.
also this will inhibit calling sendMsg(str,a,ch,d) when str == "" (but not the default one). Thats why I suggest to use std::optional instead (though we don't know what sendMsg is, it may not matter)
@463035818_is_not_a_number Yes, of course... I'll correct that.
5

Of course, use a functor:

template <typename F> void func2(F&& f) { // piece of code A f(); // piece of code B } 

Usage:

void func(int a, char ch, double d) { func2([&](){ sendMsg(a, ch, d); }); } 

A bit of explanation: Currently accepted answer is totally fine when you need to call the exactly same code with different parameters. But when you need to "inject" an arbitrary code (possibly a multiple pieces of arbitrary code) into another function, passing a temporary lambda is your best bet. Conceptually, what receiving function is seeing/getting is some abstract "callable" object (in fact, it can be anything with operator (), not just lambda) which it calls at due time. And since its a templated function, it will be compiled into zero-overhead code "as if" actual code was copy-pasted in there. The usage part is simply shows a c++ syntax to create a callable with arbitrary code in-place (I advise to read language references/tutorials on lambdas to understand the internals better).

3 Comments

Sure, please don't hesitate to ask questions.
Oh I got it. Good solution~
The only issue is that we don't know whether the OP needs to use the inputs for more than just calling sendMsg . This is of an issue with the question rather the solution here.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.