Делайте так, как делает stdlib: Не перегружайте.Например, stdlib предоставляет две функции, которые позволяют вам искать что-то в диапазоне.
Один именуется find
(например, «найдите это значение!»), А другой - find_if
(например, «найдено, если предикат возвращает истину!»).
Другой вариант может заключаться в использовании некоторого трюка SFINAE (с использованием C ++ 11 и выражения SFINAE):
template<class T>
T create();
template<class InIt, class T>
auto find(InIt first, InIt last, T const& value)
-> decltype((*first == value), create<InIt>())
{
// ...
}
Эта функция будет удалена из набора перегрузки, если *first == value
не является допустимым выражением(обычно вы не сохраняете предикаты в контейнере и выполняете поиск с тем же предикатом в нем).
, create<InIt>()
в decltype
должен придать ему тип возврата InIt
.create
не определено, потому что оно будет когда-либо использоваться только в неоцененных контекстах, и как таковое не нуждается в определении (которое облегчает жизнь, нам не нужно догадываться, как мы могли бы на самом деле построить такой объект. Мы просто беремтип InIt
).Если бы я использовал first
вместо create<InIt>()
, тип возвращаемого значения был бы InIt&
, что было бы немного удивительно и нехорошо, поскольку вы возвращаете ссылку на локальную переменную
template<class Init, class Pred>
auto find(InIt first, InIt last, Pred pred)
-> decltype((pred(*first)?0:0), create<InIt>())
{
// ...
}
Эта функция будет удалена из набора перегрузки, если pred(*first)
не является допустимым выражением, т.е. pred
не принимает value_type
из InIt
в качестве параметра.Кроме того, он будет удален, если тип возвращаемого значения pred
operator()
не может быть явно преобразован в bool
, протестировано с использованием ?:
, троичного логического оператора.Опять же, , create<InIt>()
используется для того, чтобы придать функции возвращаемый тип InIt
.
Вот небольшой живой пример на Ideone для вашего конкретного случая.Обратите внимание, что я не использовал create<int>()
здесь, потому что литерал 0
уже имеет тип int
.