Предположим, что мы имеем следующую ситуацию:
struct A
{
int i;
};
struct B
{
A a;
int other_things;
};
bool predicate( const A& a)
{
return a.i > 123;
}
bool predicate( const B& b)
{
return predicate(b.a);
}
int main()
{
std::vector< A > a_source;
std::vector< B > b_source;
std::vector< A > a_target;
std::vector< B > b_target;
std::copy_if(a_source.begin(), a_source.end(), std::back_inserter( a_target ), predicate);
std::copy_if(b_source.begin(), b_source.end(), std::back_inserter( b_target ), predicate);
return 0;
}
Оба вызова std::copy_if
генерируют ошибку компиляции, потому что правильная перегрузка функции predicate()
не может быть выведена компилятором, поскольку подпись шаблона std::copy_if
принимает любой тип предиката:
template<typename _IIter,
typename _OIter,
typename _Predicate>
_OIter copy_if( // etc...
Я нашел, что разрешение перегрузки работает, если я завершаю вызов std::copy_if
в более ограниченную функцию шаблона:
template<typename _IIter,
typename _OIter,
typename _Predicate = bool( const typename std::iterator_traits<_IIter>::value_type& ) >
void copy_if( _IIter source_begin,
_IIter source_end,
_OIter target,
_Predicate pred)
{
std::copy_if( source_begin, source_end, target, pred );
}
Мой вопрос: почему в STL он уже не ограничен таким образом? Из того, что я видел, если тип _Predicate
не является функцией, которая возвращает bool
и принимает итерированный тип ввода, она все равно будет генерировать ошибку компилятора. Итак, почему бы не поставить этот ограничитель уже в сигнатуре, чтобы разрешить перегрузку?