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:
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).
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.
First things first, there is a difference between implicit object parameter and this pointer. The former is a reference type while the latter is a keyword and is an rvalue of pointer type. For example for a const qualified non-static member function the implicit object parameter is of type const X& while the this pointer is of type const X*. While for a non-const nonstatic member function the implicit object parameter is of type X& and the this is of type X*. This can be confirmed here.
isn't Implicit object parameter the ( this ) pointer ( which ( the ( this ) pointer ) only works with non-static functions )
No, both static as well as non static member functions have an implicit object parameter for the purposes of overload resolution as can be seen from over.match.funcs#2 which states:
The set of candidate functions can contain both member and non-member functions to be resolved against the same argument list. So that argument and parameter lists are comparable within this heterogeneous set, a member function is considered to have an extra parameter, called the implicit object parameter, which represents the object for which the member function has been called. For the purposes of overload resolution, both static and non-static member functions have an implicit object parameter, but constructors do not.
(emphasis mine)
Related
I read that this code A a( A() ); was interpreted by the compiler as a function declaration while here I clearly see that A() is a function that returns an object. How can it be something else that the construction of a A object ?
I've just read entirely the Function declaration page of cppreference : https://en.cppreference.com/w/cpp/language/function and I don't see anywhere that the parameters list can look like that A().
I don't understand how The most vexing parse can be valid C++.
A() isn't a function declaration by itself, but it can be the type of a function.
For instance, suppose I declare the following function: A makeAnA();. The type of makeAnA is A(): A function that takes no arguments and returns an A.
Quoting cppreference on functions:
Each function has a type, which consists of the function's return type, the types of all parameters (after array-to-pointer and function-to-pointer transformations, see parameter list) , whether the function is noexcept or not (since C++17), and, for non-static member functions, cv-qualification and ref-qualification (since C++11). Function types also have language linkage.
So a function that has zero parameters, returns an A, and isn't noexcept has the type A().
Therefore, it's possible to interpret A a( A() ); as a function declaration. It declares that a accepts a single, unnamed argument of type A(), and returns an A as its result. Because it's possible to interpret this as a function declaration, it is required by the standard that it is so interpreted.
I am learning about classes in C++. I came across the following statement from the standard:
During overload resolution, non-static cv-qualified member function of class X is treated as a function that takes an implicit parameter of type lvalue reference to cv-qualified X if it has no ref-qualifiers or if it has the lvalue ref-qualifier. Otherwise (if it has rvalue ref-qualifier), it is treated as a function taking an implicit parameter of type rvalue reference to cv-qualified X.
The above statement seems to imply that for a const qualified non-static member function of a class X will have an implicit parameter of type const X&.
But then i also came across:
The type of this in a member function of class X is X* (pointer to X). If the member function is cv-qualified, the type of this is cv X* (pointer to identically cv-qualified X). Since constructors and destructors cannot be cv-qualified, the type of this in them is always X*, even when constructing or destroying a const object.
So according to the above second quote the implicit this parameter for a const qualified non-static member function of class Xhas type const X*.
My question is that why is there such a difference. I mean during overload resolution for a const qualfied nonstatic member function, why is the implicit parameter considered as a const X& and not simply a const X* which seems to be the actual type of this.
The implicit object parameter is not the same as this. this is a pointer referring to the object on which the member function was called while the implicit object parameter is the imagined first parameter of the member function, which is passed the object expression in the member function call (whats left of . in the member access expression) and so should be a reference parameter.
It wouldn't make sense to use a pointer for the implicit object parameter. It would make it impossible to overload the function on value category of the object expression. If a member function is &&-qualified, the implicit object parameter is a rvalue reference, so that if the object expression is a rvalue overload resolution correctly overload with a &-qualified member function.
So the implicit object parameter is const T& in your example, but this has type const T*. There is no contradiction.
This question is a follow-up of A question regarding the implementation of std::add_pointer
Under std::add_pointer
there is the following reference:
Otherwise (if T is a cv- or ref-qualified function type), provides the
member typedef type which is the type T.
Based on reading Non-static member functions: const-, volatile-, and ref-qualified member functions, my understanding is that a for a non-static member function with given cvand/or ref qualification,
a) the cv qualification of the function applies to the this pointer as well, within the scope of the function
b) the ref qualification of the function does not apply to the this pointer within the scope of the function
Given this, why is it that std::add_pointer cannot provide the member typedef type T* in the case of a non-static member function with cv or ref qualification?
Per [dcl.ptr]/4:
[ Note: Forming a pointer to reference type is ill-formed; see
[dcl.ref]. Forming a function pointer type is ill-formed if the
function type has cv-qualifiers or a ref-qualifier; see
[dcl.fct]. Since the address of a bit-field cannot be taken, a
pointer can never point to a bit-field. — end
note ]
The pointer-to-cv-qualified-function type you are imagining is actually nonexistent. Therefore, std::add_pointer cannot produce such a type :)
A non-static member function type cannot be formed. Such a thing does not exist.
struct T {
int func() const;
};
func does not have a type. You cannot ever use it as an expression on its own.
using mf = int (T::*)() const;
mf myfunc = &T::func;
mf is a pointer to member function type. It is not a function type; pointers to non-static members (including member functions) are data, not functions.
A cv or ref qualification on a member function does not qalify the function type, which does not exist, but the type of the implicit "this" parameter.
The paragraph you quote only applies to non-member or static member functions.
I'm trying to do some binding with my C++ code, and use pointer to member functions.
I have the following code :
class A
{
explicit A(float);
}
class B
{
void setA(A);
void setA(float);
}
Then I declare the pointer to member functions :
(void (B::*)(A))&B::setA
(void (B::*)(float))&B::setA
The compiler (MSVC11) finds the second line is ambiguous.
If I comment setA(A) in class B, both lines are considered ok by the compiler (!)
Is it a compiler bug?
Is there a way to circumvent that, without modifying class B's signature?
EDIT :
Actually, the code I posted was oversimplified from my real classes and did compile..
Here's a modified version that really reproduces the bug :
class A
{
public:
explicit A(float f=1.0f, float g=1.0f) {}
};
class B
{
public:
void setA(A){}
void setA(float f, float g=1.0f){}
};
with
(void (B::*)(A))&B::setA
(void (B::*)(float))&B::setA
(void (B::*)(float,float))&B::setA
The 2nd line brings a compile error :
error C2440: 'type casting' : impossible to convert 'overloaded-function' to 'void (__thiscall B::* )(float)'
I would say this is a bug. Per Paragraph 13.4/1 of the C++11 Standard:
A use of an overloaded function name without arguments is resolved in certain contexts to a function, a
pointer to function or a pointer to member function for a specific function from the overload set. [...] . The function selected
is the one whose type is identical to the function type of the target type required in the context. [...] The target can be
— an object or reference being initialized (8.5, 8.5.3),
— the left side of an assignment (5.17),
— a parameter of a function (5.2.2),
— a parameter of a user-defined operator (13.5),
— the return value of a function, operator function, or conversion (6.6.3),
— an explicit type conversion (5.2.3, 5.2.9, 5.4), or
— a non-type template-parameter (14.3.2).
Since it is pretty clear which member function from the overload set has a signature identical to the one you are explicitly casting it to, your code is legal.
Besides, your code compiles fine with Clang 3.2, GCC 4.7.2, GCC 4.8, ICC 13.0.1 and (!) VC10. See, for instance, this live example.
EDIT:
The new code you posted is indeed illegal.
The second cast cannot be resolved, because none of the member functions setA() takes only one float parameter. Therefore, the compiler doesn't know which function you mean by the expression &B::setA. Normally, it would try to disambiguate based on the contextual explicit conversion, but that doesn't help, because it specifies a signature which is incompatible with the signature of both overloads of setA().
If you are wondering why this is the case and why the second overload is not picked, then the reason is that a parameter with a default argument is still a formal parameter of your function (even if it could be omitted in some calls), and its type still counts as part of the function's signature.
Default arguments, on the other hand, are not part of a function's signature:
1.3.20 [defns.signature.member]
signature
<class member function> name, parameter type list (8.3.5), class of which the function is a member, cv-qualifiers (if any), and ref-qualifier (if any)
Now if you remove the overload setA(A), the compiler does know what member function the expression &B::setA refers to, because there is only one. No need to use the explicit cast in order to resolve the expression.
Then, since function pointers can be cast to function pointers of other types, the compiler performs an additional conversion to the specified target type.
I wrote this code in C++:
class Foo
{
public:
int& fun(){return var;} // 1st fun
int fun() const {return var;} // 2rd fun
private:
int var;
};
int main()
{
Foo foo;
int i = foo.fun();
return 0;
}
I know that C++ cannot discriminate overloading function by return value,but why when I added a const to 2rd function ,overloading can work ?
What the 'const' have done ?
Compiler cannot discriminate by return type because return values can undergo conversion before the assignment is performed. The object on which the function is invoked, on the other hand, is a parameter (albeit an implicit one) to the function, so the compiler can discriminate on it.
Const is used in the following way:
Foo inst1;
const Foo inst2;
inst1.fun(); // 1st fun
inst2.fun(); // 2nd fun
Const after the name of the function refers to the implicit this parameter. So, for inst1 it will Foo* and for inst2 const Foo*. This will guide the overload.
The return value is not used for selecting the overload. Methods/functions with the same set of params and different types of return value are not allowed on the same layer.
For what it's worth, the language from the standard (§13.3.1/3,4):
Similarly, when appropriate, the context can construct an argument list that contains an implied object
argument to denote the object to be operated on. Since arguments and parameters are associated by position within their respective lists, the convention is that the implicit object parameter, if present, is
always the first parameter and the implied object argument, if present, is always the first argument.
For non-static member functions, the type of the implicit object parameter is
— “lvalue reference to cv X” for functions declared without a ref-qualifier or with the & ref-qualifier
— “rvalue reference to cv X” for functions declared with the && ref-qualifier
where X is the class of which the function is a member and cv is the cv-qualification on the member function declaration. [ Example: for a const member function of class X, the extra parameter is assumed to have type “reference to const X”. —end example ]