Reputation: 1191
$ 20.8.2 of the standard describes the INVOKE facility that is mostly used to describe how callables are called with variadic argument lists throughout the standard library:
Define INVOKE (f, t1, t2, ..., tN) as follows:
—
(t1.*f)(t2, ..., tN)
when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T;—
((*t1).*f)(t2, ..., tN)
when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous item;—
t1.*f
when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T;—
(*t1).*f
when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types described in the previous item;—
f(t1, t2, ..., tN)
in all other cases.
What are the third and the fourth item for? As far as I can tell, they don't call f
even if f
is callable. What's the user case for them. Maybe it's a typo in the standard and *f()
was intended?
Upvotes: 6
Views: 1249
Reputation: 131829
INVOKE
is specified like that because you can actually bind member data pointers (through bind
and mem_fn
):
§20.8.10 [func.memfn]
template<class R, class T>
unspecified
mem_fn(R T::* pm);
p1 Returns: A simple call wrapper (20.8.1)
fn
such that the expressionfn(t, a2, ..., aN)
is equivalent toINVOKE(pm, t, a2, ..., aN)
(20.8.2).fn
shall have a nested typeresult_type
that is a synonym for the return type ofpm
whenpm
is a pointer to member function.
I don't think that special wording would exist if you couldn't bind member data pointers.
#include <functional>
#include <iostream>
struct X{
int n = 5;
};
int main(){
X x;
auto f = std::mem_fn(&X::n);
std::cout << f(&x) << "\n";
}
Output: 5
Upvotes: 10