Предложение о функторах прозрачных операторов существует как способ иметь обобщенные функторы, расположенные в <functional>
. Я лично считаю, что в самом предложении есть очень хороший пример, который поможет проиллюстрировать его необходимость. Однако я пойду дальше и попытаюсь объяснить и это.
Предположим, у вас есть функция, очень простая функция:
template<typename T, typename U>
auto less_than(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)) {
return std::forward<T>(t) < std::forward<U>(u);
}
Однако вы хотите использовать эту обобщенную функцию в заголовке <algorithm>
. У вас есть два варианта, чтобы сделать его структурным функтором:
struct MyLessThanFunctor {
template<typename T, typename U>
auto operator()(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)){
return std::forward<T>(t) < std::forward<U>(u);
}
};
Или в С++ 14, чтобы сделать полиморфную лямбду:
[](auto&& t, auto&& u) -> decltype(auto) {
return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u);
}
Оба они очень многословны при использовании в таком алгоритме:
int main() {
std::vector<int> v = {112,12,1281271,1919101,29181,412,1 };
std::sort(std::begin(v), std::end(v), MyLessThanFunctor()); // one
std::sort(std::begin(v), std::end(v), [](auto&& t, auto&& u) -> decltype(auto) {
return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u);
});
}
Это предложение направлено на то, чтобы сделать его более компактным и обобщенным, сделав вместо этого следующее:
std::sort(std::begin(v), std::end(v), std::less<>());
Это дает вам идеальную пересылку и решает проблемы с усечением или проблемы, возникающие при изменении контейнера, но не базового типа, назначенного контейнером, как указано в документе.
Предположим, у вас есть необобщенный функтор:
struct Functor {
bool operator()(uint32_t a, uint32_t b) {
return a < b;
}
};
И вы используете его со своим std::vector<uint32_t>
, и он отлично работает, но вы забываете о том, что ваш функтор не является обобщенным, и используете его со своим std::vector<uint64_t>
. Вы видите возникшую проблему? Элементы будут усечены перед сравнением, что, вероятно, не то, что хотел пользователь. Обобщенные функторы решают эту проблему за вас до того, как она возникнет.
person
Rapptz
schedule
19.07.2013
bool less<int>::operator()( int const& lhs, int const& rhs) const { return lhs<rhs; }
наauto less<>::operator()(LHS&& lhs, RHS&& rhs)const->decltype( std::forward<LHS>(lhs)<std::forward<RHS>(rhs) ) { return std::forward<LHS>(lhs)<std::forward<RHS>(rhs); }
, идеальную прозрачную переадресацию вызова на<
. - person Yakk - Adam Nevraumont   schedule 19.07.2013