Daily bit(e) C++. Статический operator()
Добавлено 3 сентября 2026 в 02:55
Daily bit(e) C++ 97, исправление недостатков объектов-функций (функторов) с помощью статического operator() в C++23.

В C++23 была решена давняя проблема с объектами-функциями.
Поскольку вызов operator() не мог быть статическим методом, объекты-функции (даже без состояния, aka stateless) не могли быть преобразованы в указатели на функции, и каждый вызов объекта-функции приводил к снижению производительности из-за передачи указателя this.
В C++23 operator() может быть статическим, что устраняет обе эти проблемы.
Обратите внимание, что это не затронуло лямбды, поскольку лямбды, не захватывающие указатель, всегда должны были быть преобразуемыми в указатель на функцию.
#include <utility>
namespace mynamespace
{
struct oldstyle_fn
{
// обычный способ (влечет за собой расходы на передачу указателя this),
// как внутри функции, так и в месте вызова
auto operator()(auto&& v) const
{
return std::forward<decltype(v)>(v);
}
};
struct newstyle_fn
{
// статический метод
static auto operator()(auto&& v)
{
return std::forward<decltype(v)>(v);
}
};
constexpr inline auto oldstyle = oldstyle_fn{};
constexpr inline auto newstyle = newstyle_fn{};
}
int main()
{
// передаст и &oldstyle, 10 10
int x = mynamespace::oldstyle(10);
// передаст только 10
int y = mynamespace::newstyle(10);
{
using namespace mynamespace;
// Не скомпилируется
// не сможет конвертировать функцию-член в указатель на функцию
// int (*p1)(int&&) = oldstyle_fn::operator();
// OK: функция-член -> указатель на функцию-член
int (oldstyle_fn::*p2)(int&&) const = &oldstyle_fn::operator();
(oldstyle.*p2)(10); // OK
// OK: статическая функция-член -> указатель на функцию
int (*p3)(int&&) = newstyle_fn::operator();
p3(10); // OK
}
}
