2

I am reading C++ Primer 5th edition and there I came across the following statement:

As a result, unlike ordinary function pointers, a pointer to a member is not a callable object; these pointers do not support the function-call operator.

So my question is: Is the highlighted part correct according to the standard?

My current understanding and intuition are that functionally they behave in the same manner, so a pointer to a member function should also be a callable object(as its name suggest).

Note that I am not asking whether the book is correct in saying that member function pointers do not support the function call operator. Because I already know that that part of the statement is correct. What I am asking is whether the pointer to the member function is a callable object according to the standard.

Useless
  • 64,155
  • 6
  • 88
  • 132
Jason
  • 36,170
  • 5
  • 26
  • 60
  • _"My current understanding and intuition is that functionally they behave in the same manner ..."_ they don't, can you elaborate how so? – πάντα ῥεῖ Apr 13 '22 at 14:19
  • @FrançoisAndrieux That is not my question. My question is very specific. Does the quoted statement is true according to the standard. – Jason Apr 13 '22 at 14:20
  • The book is very precise about having a function call operator. Pointers to member do not support the plain function call syntax. There is no room left to interpret this. – StoryTeller - Unslander Monica Apr 13 '22 at 14:21
  • @πάνταῥεῖ Functionally behaving the same means that they can be called. Although the syntax for calling them might be different. – Jason Apr 13 '22 at 14:21
  • 3
    So are you asking whether the book is correct in saying that member function pointers do not support the function call operator? Or are you asking whether the book is correct in asserting that only objects supporting the function call operator should be described as "callable"? – Useless Apr 13 '22 at 14:22
  • As far as comparing this to the standard, here's the standard trait: https://en.cppreference.com/w/cpp/types/is_invocable – StoryTeller - Unslander Monica Apr 13 '22 at 14:22
  • @Useless No i am not asking that whether the book is correct in saying that member function pointers do not support the function call operator. Because that is correct. What i am asking is that whether pointer to member function are callable object. – Jason Apr 13 '22 at 14:24
  • You may be confusing the concept of "calling" with the concept of "evaluating". Calling something is to execute it as a function, evaluating is to get the value of something. You can't call a pointer to member because it does not refer to a function. Maybe paired with an instance, it can refer to a callable object like `std::function` or a function pointer, but the member pointer itself is not callable. – François Andrieux Apr 13 '22 at 14:25
  • If `pFnc` is a pointer to a member function of `class A` and `object` is a `class A` object, then you can do: `(object.*pFnc)()`. Not sure if that counts as "calling", though. (For a plain old function pointer, `popFnc`, you can just do `popFnc()`, of course.) – Adrian Mole Apr 13 '22 at 14:27
  • 1
    To my great surprise, this actually turns out to be incorrect: https://eel.is/c++draft/func.def#3 - the question is well-formed, and the answer is yes. I'm not sure how useful that definition is, but it's really there. – Useless Apr 13 '22 at 14:30
  • 1
    @Albert The question may seem clear to you, but it is not clear to most other people. Many comments have asked for specific clarification. Consider directly answering those questions to help clarify what you are asking. Edit : Personally it isn't clear to me what you think "callable" means if not that it can be called as a function, so I'm not sure how to answer. – François Andrieux Apr 13 '22 at 14:35
  • "pointer to member (function)" is the only reasonable way to read that quote at all IMO. It would seem absurd to point out that you can't call a pointer to an integer data member. – Useless Apr 13 '22 at 14:51
  • NB. one of the issues with the question was that you asked about the highlighted part _in particular_. This means that you're questioning the entire quote, just with a focus on the bold part. That contradicts your own clarifying comments and the last paragraph, and was confusing. – Useless Apr 13 '22 at 14:54
  • 2
    What the book is describing is that a pointer to member function is not callable by itself. The out-of-context cited part omits that other important context. – Eljay Apr 13 '22 at 15:02
  • @Useless: Actually, (with the appropriate library facilities only) you **can** call a pointer to data member; it just returns the member (as a glvalue). – Davis Herring Feb 25 '23 at 08:08

2 Answers2

2

What i am asking is that whether pointer to member function are callable object according to the standard.

Yes, a pointer to a member function is a callable object according to the standard.

From func.def#4:

A callable object is an object of a callable type.

And from func.def#3:

A callable type is a function object type ([function.objects]) or a pointer to member.

Thus, the highlighted part of the quoted statement that says "a pointer to member is not a callable object" from C++ Primer is incorrect according the standard.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • 1
    Good answer. I'd add a note regarding the part _"these pointers do not support the function-call operator"_ for a complete answer IMHO. – YSC Apr 13 '22 at 14:39
  • @AnoopRana This answer is not for OP only, but for anyone reading it or that will read it in the future. – YSC Apr 13 '22 at 15:16
  • @FrançoisAndrieux -- this answer isn't about "callable" (whatever that means); it's about "callable object" and "callable type", and it's correct. – Pete Becker Apr 13 '22 at 15:33
  • @FrançoisAndrieux -- the question doesn't use the unadorned term "callable"; it is entirely about the technical term "callable object". There's a great deal of confusion in the comments to the question and to various answers because people are seeing only the "callable" part. That's why I keep harping on "callable object". – Pete Becker Apr 13 '22 at 15:46
  • That's fair, you're right that it looks like OP is explicitly asking about the standard library term. – François Andrieux Apr 13 '22 at 15:50
2

As a result, unlike ordinary function pointers, a pointer to member is not a callable object; these pointers do not support the function-call operator.

So my question is, if the above quoted statement(the highlighted part in particular) correct according to the standard?

To my surprise, the standard actually says in [func.def]/3

  1. The following definitions apply to this Clause:
  2. ...
  3. A callable type is a function object type ([function.objects]) or a pointer to member.
  4. A callable object is an object of a callable type.
  5. A call wrapper type is a type that holds a callable object and supports a call operation that forwards to that object.
  6. A call wrapper is an object of a call wrapper type.
  7. A target object is the callable object held by a call wrapper.

So in fact a pointer to member function is a callable object according to the standard ... in the context of describing which types can be the target of the function objects defined in <functional>.

There is no alternative definition of a "callable object" in the standard that would correspond to the more general sense implied by the book.


Summary:

  1. The only standard definition of a callable object is when defining the types that are valid targets for the function objects in <functional>.

    A pointer to member function is a valid target, and is callable so long as the instance pointer is either bound or passed to the function call

  2. The customary definition of a callable object as one providing a function call operator is not directly supported by the standard.

    This definition is arguably more useful though, because it tells me how I can use the object.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • 1
    There is no other more-general definition of "callable" in the standard that I can see, and I can't see any other way of interpreting that "... **or a pointer to member**" that makes sense. Unless it means pointer-to-a-callable-data-member or something? – Useless Apr 13 '22 at 14:50
  • The point of "callable object" and "callable type" is that they tell you what objects and what types you can use with the various standard library functions that provide function calls, such as `std::bind` and `std::function`. – Pete Becker Apr 13 '22 at 15:03
  • Yeah, you're both absolutely right. I've rewritten this so the context is clear, and distinguished from the customary definition used in the book – Useless Apr 13 '22 at 15:07
  • Is there a reason why this discrimination is done? I mean why only when *" instance pointer is either bound or passed to the function call"*. Why not in general. For example, in [this demo](https://onlinegdb.com/zlntZvIna) why don't we consider `ptr` a callable object but when the instance pointer is bound or passed to the function call then it is considered a callable object. Is there a reason for this difference. The behavior should be same IMO in both the cases. – Jason Apr 13 '22 at 15:17
  • @Albert -- `void (S::*ptr)()`: `ptr` is a callable object, because it's a pointer to member. – Pete Becker Apr 13 '22 at 15:28
  • @FrançoisAndrieux -- a pointer-to-member-function is a "callable object" because it's a pointer-to-member. A pointer-to-member-data is a "callable object" for the same reason. `[expr.call]` is about something completely different. – Pete Becker Apr 13 '22 at 15:31
  • @PeteBecker Ok, I had the understanding that pointer to member was a synonym to pointer to data member. I'll go revise/remove my incorrect comments now. – François Andrieux Apr 13 '22 at 15:34
  • @PeteBecker Ok, so in my [demo](https://onlinegdb.com/zlntZvIna), the pointer to member function named `ptr` is indeed a callable object right? But then in this answer, why is it written that *"in the context of describing which types can be the target of the function objects defined in "*. So, since in my [demo](https://onlinegdb.com/zlntZvIna), we're not using `` thus `ptr` should not be a callable object. But you said it is. I am getting confused. Sorry i am just a beginner and i thought my original question was simple. – Jason Apr 13 '22 at 15:34
  • @Albert -- is a 3 not an integer, just because you don't do arithmetic on it? The definition of "callable object" says that `ptr` is a callable object. – Pete Becker Apr 13 '22 at 15:36
  • @PeteBecker Thanks for the confirmation. But by reading this answer(in particular the *"in the context of ..."* part), i got confused. So to clarify that i asked. Thanks again. – Jason Apr 13 '22 at 15:42
  • 1
    I would argue in that demo, that `(s.*ptr)` is callable in the customary sense, because you can write the function call `(s.*ptr)()` - but `(s.*ptr)` isn't an object. Conversely `ptr` is not callable in the customary sense because you can't write a function call as `ptr()` on its own. – Useless Apr 13 '22 at 15:42
  • At the bottom of this slippery slope is UFCS — full of syntactic saccharine. And [std::invoke](https://en.cppreference.com/w/cpp/utility/functional/invoke) isn't it. – Eljay Apr 13 '22 at 16:52