Некоторые действия можно выполнить двумя способами: изменить передаваемый аргумент или вернуть результат в виде отдельного значения. Типичный пример — операторы += и +. Обычно первый записывает результат в левый операнд, а второй возвращает временное значение. Мне понадобилось определить несколько вспомогательных функций для работы со строками, и тут я столкнулся с аналогичной ситуацией. Например, функцию удаления замыкающих пробельных символов можно реализовать в двух вариантах
// пишем результат в аргумент и возвращаем ссылку на аргумент
string& remove_trailing_whitespaces(string& s);
// возвращаем результат в виде временного объекта
string remove_trailing_whitespaces(const string& s);
Хотелось бы иметь сразу оба варианта, но я пока не могу сообразить, как бы их получше совместить. Такая перегрузка меня не устраивает, так как легко будет допустить ошибку. Можно дать функциям разные названия, но какие? Коверкать названия приписыванием какой-нибудь невнятной абракадабры не хочется. Приставки или суффиксы, если уж их использовать, должны быть достаточно информативными, но не слишком длинными. Ничего подходящего я придумать не смог Может, в Boost или других библиотеках есть примеры разруливания такой ситуации?
Re: Два способа возврата результата для одного действия
Здравствуйте, unhelper, Вы писали:
U>Некоторые действия можно выполнить двумя способами: изменить передаваемый аргумент или вернуть результат в виде отдельного значения. Типичный пример — операторы += и +. Обычно первый записывает результат в левый операнд, а второй возвращает временное значение. Мне понадобилось определить несколько вспомогательных функций для работы со строками, и тут я столкнулся с аналогичной ситуацией.
Стандартная библиотека C++ использует схему именования verb и verb_copy.
В Python’е есть функции sort (сортирующая массив на месте и не возвращающая ничего) и sorted (возвращающая сортированную копию исходного массива).
В некоторых случаях можно и вовсе определять только чистую функцию или только деструктивную.
Re: Два способа возврата результата для одного действия
Здравствуйте, unhelper, Вы писали:
U>Хотелось бы иметь сразу оба варианта, но я пока не могу сообразить, как бы их получше совместить.
Вопрос именно в названии, или в том, как реализовать без дублирования кода?
Если в названии, — то, конечно, надо оглядываться на уже сложившуюся в твоём проекте практику. Если такой ещё нет, то предлагаю
— remove_trailing_spaces_inplace / remove_trailing_spaces
Если в реализации, то
— с преждевременной пессимизацией, — выразить одну функцию через другую, и затем дошлифовывать производительность по мере нужды
— написать промежуточную функцию, например, на итераторах, которую можно натравить на begin(src),end(src),back_inserter(dst) либо begin(src),end(src),begin(src).
Перекуём баги на фичи!
Re[2]: Два способа возврата результата для одного действия
Здравствуйте, Centaur, Вы писали:
C>Стандартная библиотека C++ использует схему именования verb и verb_copy.
C>В Python’е есть функции sort (сортирующая массив на месте и не возвращающая ничего) и sorted (возвращающая сортированную копию исходного массива).
Здравствуйте, unhelper, Вы писали:
U>Например, функцию удаления замыкающих пробельных символов можно реализовать в двух вариантах
U>
// пишем результат в аргумент и возвращаем ссылку на аргумент
U>string& remove_trailing_whitespaces(string& s);
U>// возвращаем результат в виде временного объекта
U>string remove_trailing_whitespaces(const string& s);
Я бы ожидал использование библиотечных функций в данном случае.
Например: здесь:
U>Может, в Boost или других библиотеках есть примеры разруливания такой ситуации?
Boost использует суффикс _copy, но не всегда следует смотреть на boost. Важнее принятый для конкретного проекта стиль именования и кодирования.
И каждый день — без права на ошибку...
Re[2]: Два способа возврата результата для одного действия
Здравствуйте, Аноним, Вы писали:
BFE>>Это не удобно. Часто хочется написать нечто, вроде: BFE>>
BFE>> if ( 0 == remove_trailing_whitespaces(strName).size() )
BFE>> return;
BFE>>
А>Весьма плохо иметь в подобном выражении побочный эффект, это чреватое трудноуловимыми ошибками объединение двух операций в одну.
Ни разу за свою многолетнюю практику я не сталкивался с трудноуловимыми ошибками такого рода.
Обычно трудноуловимые ошибки сводятся к чему-то такому:
assert(boost::filesystem::exists( "foo" ) == boost::filesystem::exists( "foo" ));
т.е. к ошибкам многопоточности.
А>Это, кстати, нарушение базового принципа Command-Query Separation.
if ( 0 == remove_trailing_whitespaces(remove_trailing_whitespaces(strName)).size() )
return;