Почему std::function принимает указатель на элемент данных?

Этот код извлечен и упрощен из std::function

#include <functional>
#include <iostream>
 
struct Foo
{
    int num_;
};

int main()
{
    const Foo foo(314159);
     // store a call to a data member accessor
    std::function<int(Foo const&)> f_num = &Foo::num_;
    std::cout << "num_: " << f_num(foo) << '\n';
}

Почему этот std::function принимает указатель на элемент данных и почему f_num(foo) полностью работает?

Я проверил, что он использовал этот конструктор:

#if _USE_FUNCTION_INT_0_SFINAE
    template <class _Fx, typename _Mybase::template _Enable_if_callable_t<_Fx&, function> = 0>
#else // ^^^ _USE_FUNCTION_INT_0_SFINAE // !_USE_FUNCTION_INT_0_SFINAE vvv
    template <class _Fx, class = typename _Mybase::template _Enable_if_callable_t<_Fx&, function>>
#endif // _USE_FUNCTION_INT_0_SFINAE
    function(_Fx _Func) {
        this->_Reset(_STD move(_Func));
    }

https://godbolt.org/z/vTKfsWMhG

Он специально разработан для этого (он использует std::invoke под капотом), и результирующая функция вернет этот член. Позволяет вам делать всевозможные умные вещи, например std::ranges::sort для определенного члена класса (путем передачи ему указателя-члена в качестве проекции) (он не использует std::function, но использует std::invoke).

HolyBlackCat 18.08.2023 12:50

Указатель данных члена, прикрепленный к соответствующему объекту, приводит к ссылке. Поведение аналогично унарной функции доступа, вызываемой для объекта. Поэтому std решил рассматривать его как унарную функцию; за исключением того, что вы не можете обычно вызывать его с помощью оператора вызова функции (operator()). Это казалось удобным, когда они это решили. В настоящее время рекомендуется оборачивать привязки членов как лямбда-выражения для эффективности использования памяти ([object]{return object.data;} или [smart_ptr]{return smart_ptr->method();}).

Red.Wave 18.08.2023 21:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
97
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Конструктор std::function принимает указатель на элемент данных, так как он Callable. Это работает из-за std::invoke под капотом.

Вот что происходит:

  • Конструктор std::function принимает указатель на элемент данных.
  • Когда вы вызываете f_num(foo), он использует std::invoke, который знает, как обрабатывать указатели на элементы данных. В этом контексте он рассматривает указатель как функцию, которая принимает объект и возвращает указанный элемент данных.
  • Это позволяет выполнять такие операции, как сортировка по определенным членам класса, предоставляя универсальный способ работы с членами класса.

Использование указателей членов таким образом соответствует стандарту C++ и позволяет использовать в коде некоторые мощные шаблоны.

Хотя это и не ложь, этот текст звучит так, как будто комментарии были скопированы в ИИ, который вставил какой-то пушистый маркетинговый ход.

j6t 18.08.2023 13:26

Может поэтому первый комментарий удалили

Fareanor 18.08.2023 13:45

Другие вопросы по теме