When parsing a construct, which can be either a declaration, or an expression known as the uncertainty of most Vexing Parse, the standard states that “permission should consider any construct that can be a declaration of declaration”.
Both (2) and (4) are valid declarations, therefore they should be analyzed as declarations. Both (3) and (4) declare a function foo function of type A*() aka "that does not pass a pointer to A "
6.8 Ambiguity resolution [stmt.ambig]
There is ambiguity in the grammar, including statement expressions and declarations: an expression-expression with an explicit type conversion in the style of the function (5.2.3) as its left-most subexpression may be indistinguishable from the declaration in which the first declarator begins with a. In these cases, the operator is the declaration. [Note. To resolve the ambiguity, the entire query may need to be examined to determine if it is an expression expression or declaration. This is a multitude of examples. [Example: it is assumed that T is a specifier of a simple type (7.1.5),
T(a)->m = 7; // expression-statement T(a)++; //expression-statement T(a,5)<<c; //expression-statement T(*d)(int); //declaration T(e)[5]; //declaration T(f) = { 1, 2 }; // declaration T(*g)(double(3)); // declaration
In the last example above, g, which is a pointer to T, is initialized to double (3). This, of course, is informal for semantic reasons, but it does not affect the parsing. -end example]
8.2 Ambiguity resolution [dcl.ambig.res]
Uncertainty arising from the similarity between function style coercion and the declaration mentioned in 6.8 may also arise in the context of the declaration. In this context, the choice is between declaring a function with an excessive set of parentheses around the parameter name and declaring the object using the style function as an initializer. In the same way as for the ambiguities mentioned in 6.8, it is permitted to consider any construction that may be a declaration of a declaration . [Note: the declaration can be explicitly eliminated using an ineffective style using a = to indicate initialization or by removing redundant parentheses around the parameter name. ] [Example:
struct S { S(int); }; void foo(double a) { S w(int(a));
-end example]