0. Я тут на днях увидел, что иногда форвардят не только какие-то аргументы при вызове
operator() у функторов, но и и сами функторы. Пример из вероятной реализации std::apply:template<class F, class Tuple, std::size_t... I>
decltype(auto) apply_impl(F&& f, Tuple&& t, index_sequence<I...>) {
return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
}
template<class F, class Tuple>
decltype(auto) apply(F&& f, Tuple&& t) {
using Indices = make_index_sequence<std::tuple_size<Tuple>::value>;
return apply_impl(std::forward<F>(f), std::forward<Tuple>(t), Indices());
}В
apply_impl есть такая строчка:return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);Зачем это делать для самого функтора?
Дело в том, что в пользовательском функторе
operator() могут быть перегружены по категории значения:operator()() & {…}
operator()() && {…}И если вы не форвардите сам функтор, вы теряете его категорию значений, что может привести к вызову не той перегрузки.
1. Доклад Andrei Alexandrescu с CppCon 2023 про улучшение бинарного поиска и размышления про ChatGPT. Как обычно, очень харизматичный чувак. И, как обычно, хороший доклад.
2. Маленький пост про заблуждения в распределённых системах. В целом довольно очевидный, но от этого не менее полезный.