Search code examples
c++constructordeclarationambiguity

Meaning of "ill-formed declaration" in L(n)


A code snippet from cppreference.com is like this:

struct M { };
struct L { L(M&); };
 
M n;
void f() {
    M(m); // declaration, equivalent to M m;
    L(n); // ill-formed declaration
    L(l)(m); // still a declaration
}

L(n); is commented with "ill-formed declaration".

But nearly all compilers issue message like this: no default constructor exists for class "L". That is to say, it's not considered to be ill-formed, right? Because if i throw a line L() = default; into L's body, it compiles successfully.

Is the comment wrong or misleading or compilers are not strictly standard-conforming?

Follow Up

Seems that i made something wrong with ill-formed:

ill-formed - the program has syntax errors or diagnosable semantic errors. A conforming C++ compiler is required to issue a diagnostic, > even if it defines a language extension that assigns meaning to such > code (such as with variable-length arrays). The text of the standard > uses shall, shall not, and ill-formed to indicate these requirements.

In light of that, that line is semantically wrong.

Thanks, for you guys' answers and comments.


Solution

  • I think that the example demonstrates that declarator may be enclosed in parentheses.

    So this declaration

    M(m);
    

    is equivalent to

    M m;
    

    that is there is declared an object m of the type M.

    However this record

    L(n);
    

    can be considered as an expression statement with calling the constructor L( M & ) with the argument n of the type M or as a declaration.

    The C++ Standard resolves such an ambiguity as a declaration instead of the expression statement. So in this record n is the name of the created object. But the class L does not have the default constructor. So the declaration is ill-formed because the structure L does not have the default constructor that is required for this declaration.

    From the C++ 14 Standard (6.8 Ambiguity resolution)

    1 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 make an expression statement instead of the declaration you can write for example

    ( L )( n );
    

    This record

    L(l)(m);
    

    is a correct declaration. There is declared the object l of the type L using the constructor L( M & ).