Vincent
Vincent

Reputation: 60381

Are function pointers function objects in C++?

The C++ standard defines function objects as:

A function object type is an object type that can be the type of the postfix-expression in a function call. (link)

First I was thinking that function objects were functors, but then I realized that for a function pointer ptr of type P (not a function, but a function pointer), std::is_object_v<P> is true and can be called with the ptr(Args...) syntax.

I am right that function pointers are considered as function objects by the standard? And if they are not what part of the definition is not satisfied by function pointers?

Upvotes: 11

Views: 1877

Answers (3)

Swift - Friday Pie
Swift - Friday Pie

Reputation: 14589

The function pointer are function object, but they also have a funny quirk coming from C era:

#include <iostream>

int foo(int a)
{
    std::cout << "Hello, " << a << " stars\n";
    return a;
}
    
int (*pr) (int) = foo;

int main()
{
    pr(0);
    (*pr)(1);
    (**pr)(2);
    (***pr)(3);
    return 0;
}

The postfix expression shall have function type or pointer to function type and function is contextually convertible to a function pointer whenever such conversion is required, so repeating dereference operators bounce type "to and fro", leaving it be a function pointer. Captureless lambda would do too:

// also can write `auto pr2 = ...`
int (*pr2) (int) = [](int a)->int { 
         std::cout << "Hello, lambda " << a <<  " stars\n"; return a; 
};

// in main()
(**pr2)(2);

Naturally, that code is ill-formed if pr is a generalized "functor"

int b = 2;
auto pr3 = [=]()->int { 
   std::cout << "Hello, general lambda " << b << std::endl; 
   return b; 
};

pr3();
//(*pr3)();  Ill-formed: not a pointer!

Upvotes: 0

Swift - Friday Pie
Swift - Friday Pie

Reputation: 14589

Function pointer is what it sounds like: a pointer to function. As itself it's a storage containing a pointer object, which returns a callable of function type.

If you take time and read first chapters of standard, you 'll understand that any variable declaration declares some type of storage that contains objects. Those can be objects of primitive types or classes. Essentially in C++ anything that can be stored is object.

By declaring function pointer you create storage that can store address of that function and operator() can be used

Anther type of callable closure can be created by lambda expression. They are not function objects, each expression creates a unique callable object, but captureless lambdas can be used as one, e.g. to assign it to a function pointer, e.g.

double (*square)(double) = [](double a)->double { return a*a; };

after this you can call it using expression like square(3.6);

For functions and lambda call operator operator() is supplied by language, by defining operator() for a class you create what people often call "functor", which is misnomer because actual functors in mathematics or such languages like Haskell do not store state. Result of lambda expression is a "functor" created by compiler, which stores states of captured objects.

Naming those objects callable might be a little misleading too, because as a concept in C++, a callable object is any object that can be used with INVOKE operation, which include pointers to data members even while no function calls happen.

it leaves only one option, if we can use function call with said object, it's a function object. It can be function, lambda expression, function object, function pointer, member function pointer with specified class instance ( obj.*memberptr or objptr->*memberptr - call of member function is very special) - they are function objects.

Upvotes: 2

T.C.
T.C.

Reputation: 137315

Yes, they are. The term "object" in C++ standard does not mean "object" in the OOP sense. An int is an object.

Upvotes: 17

Related Questions