Why does INVOKE facility in the C++11 standard ref

2019-01-26 11:45发布

问题:

$ 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?

回答1:

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>
unspecifiedmem_fn(R T::* pm);

p1 Returns: A simple call wrapper (20.8.1) fn such that the expression fn(t, a2, ..., aN) is equivalent to INVOKE(pm, t, a2, ..., aN) (20.8.2). fn shall have a nested type result_type that is a synonym for the return type of pm when pm 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

Live example.