Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are static member functions considered to have an implicit object parameter during overload resolution?

In this link : Implicit object parameter

In this quote :

If any candidate function is a member function (static or non-static) that does not have an explicit object parameter (since C++23), but not a constructor, it is treated as if it has an extra parameter (implicit object parameter) which represents the object for which they are called and appears before the first of the actual parameters.

I do not understand why the word static is mentioned here? Isn't the implicit object parameter the this pointer ( which only exists in non-static functions ) ?

Edit in this link : link

quote :

The keyword this is a rvalue (until C++11)prvalue (since C++11) expression whose value is the address of the implicit object parameter (object on which the non-static member function is being called). It can appear in the following contexts:


2 Answers

It's useful to consider examples. When you have:

struct C {
    void f(int);
    void f(int) const;
};

C c;
c.f(42);

How does overload resolution pick? You effectively have a choice of:

//     implicit object  | regular
//         parameter    | parameter
void f(C&,                int        );
void f(C const&,          int        );

With the arguments (C, int). That ends up picking the first one, for being a better match.


Now, let's think of this example:

struct D {
    static void g(int);
    void g(long);
};

D d;
d.g(42);

Now, if we try to do the same thing:

//     implicit object  | regular
//         parameter    | parameter
void g(????????,          int        );
void g(D&,                long        );

We have two arguments, a D and an int. We don't know if we're going to call a static function or not yet, we still have to do overload resolution. How do we pick in this case? The non-static member function has an implicit object parameter, D&, but what do we do for the static one?

The C++ answer is we contrive a fake parameter, that is a perfect match for everything:

//     implicit object  | regular
//         parameter    | parameter
void g(contrived-match,   int        );
void g(D&,                long        );

And now, when we do overload resolution with (D, int), you can see that the static function is the best match (better conversion sequence for the second parameter).

Once we pick the static member function, we then ignore the object argument entirely. d.f(42) basically evaluates as D::f(42). But we didn't know that until we performed overload resolution - the contrived parameter exists to solve the problem of how to actually compare these cases.

This still applies even if there were just the one static member function - since d.f(42) does have two parameters: the d and the 42, so the language needs to handle the d somehow (the alternative could've been to simply disallow this syntax, requiring D::f(42) if you wanted to call a static member function, but that seems a lot less nice).

like image 186
Barry Avatar answered Jan 20 '26 09:01

Barry


Consider what happens if you don't have this rule and have a static method and non-static method with the same (explicit) parameters. Then to the non-static method an additional implicit parameter (this) will be added, but not to the static method. This will make the list of parameters of both methods different and will allow to overload the static method with non-static method with the same explicit parameters.

like image 23
Alex Sveshnikov Avatar answered Jan 20 '26 11:01

Alex Sveshnikov