Функции-члены, вызываемые для не указательных объектов с помощью функции std :: function - PullRequest
0 голосов
/ 20 апреля 2020

Код следующий:

std::string::empty() должен принимать указатель this в качестве параметра, тип которого pointer , std::string *.

Как может ли вызов в строке 2 и 3 быть в порядке?

#include <iostream>
#include <functional>

int main() {
    std::string str{"A small pond"};

    std::function<bool(std::string*)> fp = &std::string::empty;
    std::cout << fp(&str) << std::endl; // 1

    std::function<bool(std::string)> f = &std::string::empty;
    std::cout << f(str) << std::endl; // 2

    std::function<bool(std::string&)> fr = &std::string::empty;
    std::cout << fr(str) << std::endl; // 3
}

/*
output:
0
0
0
*/
clang version 9.0.0-2~ubuntu18.04.2 (tags/RELEASE_900/final)
g++ (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0

1 Ответ

2 голосов
/ 20 апреля 2020

std::function может принять любой Callable , который соответствует его сигнатуре типа. При вызове вызываемый и аргументы оцениваются по следующим правилам (цитата cppreference ):

  • Если f - указатель на функцию-член класса T:
    • Если std::is_base_of<T, std::decay_t<decltype(t1)>>::value равно true, то INVOKE(f, t1, t2, ..., tN) эквивалентно (t1.*f)(t2, ..., tN)
    • Если std::decay_t<decltype(t1)> является специализацией std::reference_wrapper, то INVOKE(f, t1, t2, ..., tN) эквивалентно (t1.get().*f)(t2, ..., tN)
    • Если t1 не удовлетворяет предыдущим пунктам, то INVOKE(f, t1, t2, ..., tN) эквивалентно ((*t1).*f)(t2, ..., tN).

Таким образом, первый случай оценивается как (*t1).*f(), а два других - как t1.*f().

...