Daily bit(e) C++. Статический operator()

Добавлено 3 сентября 2026 в 02:55

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

Daily bit(e) C++

В 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
    }
}

Пример на Compiler Explorer

Теги

C++ / CppDaily bit(e) C++Программирование