Это std::bind
, будучи умным, а не указателем.
Как описано в Callable, при вызове указателя на нестатическую функцию-член или указателя на нестандартныйчлен статических данных, первый аргумент должен быть ссылкой или указателем (включая, возможно, умный указатель, такой как std :: shared_ptr и std :: unique_ptr) на объект, к которому будет получен доступ.
* Реализуется 1010 *, поэтому он может принимать умный указатель вместо необработанного указателя.
В реализации glibc ++ вы можете видеть, что bind
внутренне вызывает invoke
:
// Call unqualified
template<typename _Result, typename... _Args, std::size_t... _Indexes>
_Result
__call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
{
return std::__invoke(_M_f,
_Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)...
);
}
И std::invoke
работает со смарт-вещами (указатели, справочные обертки и т. Д.) "Из коробки":
INVOKE(f, t1, t2, ..., tN)
определяется следующим образом:
Если 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)
.