У меня нет ни одного сложного предпочтения. В зависимости от обстоятельств я чередую большинство ваших примеров.
Другой вариант, который я иногда использую, похож на ваш Range
пример, но с использованием простых старых диапазонов итераторов:
template <typename Iter>
void f(Iter first, Iter last);
, у которого есть приятное свойство: он легко работает как со строками в стиле C (и позволяет вызываемому абоненту определять длину строки в постоянном времени), так и с std::string
.
Если шаблоны проблематичны (возможно, потому что я не хочу, чтобы функция была определена в заголовке), я иногда делаю то же самое, но используя char*
в качестве итераторов:
void f(const char* first, const char* last);
Опять же, его можно тривиально использовать как с C-строками, так и с C ++ std::string
(насколько я помню, C ++ 03 явно не требует, чтобы строки были смежными, но каждая известная мне реализация использует смежные строки, и я верю, что C ++ 0x явно потребует это).
Таким образом, обе эти версии позволяют мне передавать больше информации, чем простой параметр const char*
в стиле C (который теряет информацию о длине строки и не обрабатывает встроенные нули), в дополнение к поддержке обеих основных строк типы (и, возможно, любой другой класс строк, который вы можете придумать) идиоматическим образом.
Недостатком является то, что вы получите дополнительный параметр.
К сожалению, обработка строк на самом деле не самая сильная сторона C ++, поэтому я не думаю, что есть единственный «лучший» подход. Но пара итераторов - один из нескольких подходов, которые я склонен использовать.