How the C++ most vexing parse is possible in this example? - c++

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.

Related

Implicit object parameter C++

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)

C++ temporary class instantiation ambiguously

Let we have procedure formed as class. Only constructor call makes some side effect. No need to handle class instance in memory after call. Following code instantiate that class:
struct A{
A(int){}
};
int main() {
A(0);//right. Pass const to ctor
int x=0;
A(x);//bad. Compiler interpret like A x;
(A(x));//right. New temporary object passed to brackets
A((int)x);//right. Pass temporary int to ctor
return 0;
}
(see also on Online IDE)
Why A(x); interpret as variable x declaration instead of temporary A object instantiaton?
From the C++11 standard, ISO/EIC 14882 §6.8 [stmt.ambig] ¶1 (emphasis mine):
There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable
from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.
To apply this to your question, A(x); can parse as either "call the function A / construct a temporary object of type A, and pass x as the only function/constructor argument" or "declare a variable x of type A." The standard says that in this case, it should be parsed as a variable declaration.
Your other examples are not ambiguous because they cannot be parsed as a variable declaration, and so they are parsed as a call to A's constructor.
That's because what you consider should be the parameter list to the ctor, (x) is being interpreted as "x in parentheses". Thus, A(x) is read as A (x) is read as A x.
In the other cases, the compiler has a hint suggesting that it should generate an A instance, calling the ctor with the arguments supplied.

C++11 initializer with ambiguous function id-expression?

In the following C++11 code:
void f(int) {}
void f(double) {}
void (*p)(int) = f;
There are two functions.
The third f identifier is an id-expression and the initializer of p.
In 5.1.1p8 [expr.prim.general]/8 it says:
The type of the [id-expression] is the type of the identifier.
The result is the entity denoted by the identifier. The result is an lvalue if the entity is a function, variable, or data member and a prvalue otherwise.
Given that f could be referring to two different entities with two different types, there is no "the entity" or "the type".
Is there some other text in the standard that addresses this situation?
Do implementations just disambiguate this as an extension or is it required somewhere? (Without some other text one could argue that an implementation could reject the f id-expression as ambiguous.)
The standard (at § 13.4) defines that:
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. A
function template name is considered to name a set of overloaded
functions in such contexts. The function selected is the one whose
type is identical to the function type of the target type required in
the context.
Emphasis mine.
After the quote, there is an example (at § 13.4/5) that resembles yours:
int f(double);
int f(int);
int (*pfd)(double) = &f; // selects f(double)
int (*pfi)(int) = &f; // selects f(int)
As far as the unary & is concerned, the standard specifies that (at § 5.3.1/6 and thanks to jogojapan):
The address of an overloaded function can be taken only in a context
that uniquely determines which version of the overloaded function is
referred to.
but can also be omitted (at § 13.4/1):
The overloaded function name can be preceded by the & operator.
(again, emphasis mine) just like you did, in your example.

What is "myfunc" vs "myfunc()"

A noob question that probbaly applies to C as well as C++. Let's say I have
void myfunc() {
blah;
}
So, I call this function with:
myfunc();
However, no compiler error is produced when I "call" it with:
myfunc;
Program runs, but myfunc doesn't get called. So, what is C++ interpreting this as?
Now, I'm doing this in the Arduino IDE, all one big lump of code, so I don't get segfaults, etc. So maybe this would throw a runtime error on a dynamically linked host.
myfunc without the parens is the address of the function in memory.
For example, if you have to pass a function to some other function, you would do it with that.
A good example of this is in bsearch in the c standard library, where you need to pass a user defined comparator function in order to do a generic search.
The compiler just evaluates the expression. Since you're evaluating the name of a function, it's basically a no-op.
It's just like this:
int main() {
42; // evaluates 42 but does nothing with it
}
Your compiler should warn you that the result of the expression is unused, anyway.
In C myfunc or any other function name represents the function itself, which will be implicitly converted to a function pointer
Function to pointer
An lvalue of function type T can be implicitly converted to a prvalue pointer to that function. This does not apply to non-static member functions because lvalues that refer to non-static member functions do not exist.
https://en.cppreference.com/w/cpp/language/implicit_conversion#Function_to_pointer
and () is an operator that when applies to a function pointer or a function object will invoke that function
Built-in function call operator
The function call expressions have the form
E ( A1, A2, A3,... )
where
E is an expression that names a function
A1, A2, A3,... is a possibly empty list of arbitrary expressions, except the comma operator is not allowed at the top level to avoid ambiguity.
The expression that names the function can be
lvalue expression that refers to a function
pointer to function
explicit class member access expression that selects a member function
implicit class member access expression, e.g. member function name used within another member function.
So without the function-call operator myfunc; is just a no-op expression that contains a function pointer. If you've turned on compiler warnings (which you should really do) then they'd shout at you about the issue. GCC says that
statement is a reference, not call, to function 'func' [-Waddress]
warning: statement has no effect [-Wunused-value]
while Clang outputs warning: expression result unused [-Wunused-value]

Pointer to member function weirdness

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.