#c #c 11 #overloading
Вопрос:
У меня есть пара перегруженных функций:
void func(const std::stringamp; 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
и piece of code B
являются точно такими же, разница только в параметре sendMsg
.
Есть ли какой-то способ избежать дублирования кода?
Комментарии:
1. Как выглядит sendMsg?
2. @mfnx Это не имеет значения, нет?
sendMsg
это библиотечная функция, которая выполняет некоторую работу с сокетами. Я все равно не могу это изменить.3. Я не понял вопроса. Почему мы не можем переместить A и B в его собственные функции? Кто-нибудь, пожалуйста, объясните.
4. @Yves вот в чем проблема с вопросом, как избежать кода, не показывая код 😉 Не беспокойтесь, я думаю, что это общая трудность с такого рода вопросами
5. Вопрос IMO лишен важных деталей. Эти ответы на ответы
not suitable for my case
являются лучшим доказательством этого.
Ответ №1:
шаблон может быть возможностью:
template <typename ... Ts>
auto func(const Tsamp;... args)
-> decltype(sendMsg(args...), void()) // SFINAE to only allow correct arguments
{
// piece of code A
sendMsg(args...);
// piece of code B
}
но движение // piece of code A
по своей собственной функции, вероятно, было бы моим выбором.
Ответ №2:
Вам пришлось бы сделать что-то вроде
void codeA() {
// ...
}
void codeB() {
// ...
}
void func(const std::stringamp; 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. Ну, добавьте две функции, которые не подходят для моего случая.
Ответ №3:
Другая идея состояла бы в том, чтобы присвоить значение по умолчанию str
:
void func(int a, char ch, double d, const std::stringamp; str = "")
{
// piece of code A
if (str.empty()) sendMsg(a, ch, d);
else sendMsg(str, a, ch, d);
// piece of code B
}
Комментарии:
1. это может быть
const std::stringamp;
также по умолчанию.2. также это будет препятствовать вызову
sendMsg(str,a,ch,d)
, когдаstr == ""
(но не по умолчанию). Вот почему я предлагаю использоватьstd::optional
вместо этого (хотя мы не знаем, чтоsendMsg
это такое, это может не иметь значения)3. @463035818_is_not_a_number Да, конечно… Я это исправлю.
Ответ №4:
Конечно, используйте функтор:
template <typename F> void func2(Famp;amp; f) {
// piece of code A
f();
// piece of code B
}
Использование:
void func(int a, char ch, double d) {
func2([amp;](){ sendMsg(a, ch, d); });
}
Небольшое объяснение: Принятый в настоящее время ответ полностью подходит, когда вам нужно вызвать один и тот же код с разными параметрами. Но когда вам нужно «внедрить» произвольный код (возможно, несколько фрагментов произвольного кода) в другую функцию, передача временной лямбды-ваш лучший выбор. Концептуально, то, что приемная функция видит/получает, — это какой-то абстрактный «вызываемый» объект (на самом деле, это может быть что угодно с operator ()
, а не только лямбда), который он вызывает в свое время. И поскольку это шаблонная функция, она будет скомпилирована в код с нулевыми накладными расходами, «как если бы» фактический код был скопирован туда. Часть использования просто показывает синтаксис c для создания вызываемого объекта с произвольным кодом на месте (я советую прочитать ссылки на языки/учебные пособия по лямбдам, чтобы лучше понять внутреннее устройство).
Комментарии:
1. Конечно, пожалуйста, не стесняйтесь задавать вопросы.
2. О, я понял. Хорошее решение~
3. Единственная проблема заключается в том, что мы не знаем, должна ли ОПЕРАЦИЯ использовать входные данные для большего, чем просто вызов
sendMsg
. Это связано с вопросом, а не с решением здесь.