Search code examples
c++language-lawyer

Why are pointers to data members callable in C++?


Under the "Callable" page at cppreference it states:

Notes: Pointers to data members are Callable, even though no function calls take place.

Pointers to function members makes sense: why are pointers to data members Callable if they can't be called?


Solution

  • Pointers to data members are callable types by definition.

    Note that this doesn't refer to the use of the call operator (), since data member pointers and member function pointers cannot have the () operator applied to them; however they can be invoked. The exposition-only expression INVOKE (exposed through std::invoke) works with any callable type.

    For a data member pointer f, INVOKE(f, t) expands to t.*f ([func.require] p1.4). Thus, data member pointers act like a function that returns a member of an object.

    Callable data member pointers are useful

    They can be very useful as projections in the new C++20 algorithms:

    struct S { int x; };
    std::vector<S> range = /* ... */;
    
    // sort range using std::ranges::less and using &S::x as a projection
    std::ranges::sort(range, {}, &S::x);
    

    Such a call to std::ranges::sort would sort range by comparing the x member of each S object. This works because algorithms accept any callable type, not just types with a call operator.

    Note on language development

    Admittedly, the terminology is very confusing. In hindsight, "callable types" should have been named "invocable types" instead.

    There have also been proposals to add a () operator to member pointers; most recently, there is P1214: Pointer to Member Functions and Member Objects are just Callables!.