Search code examples
c++c++11syntaxlanguage-lawyer

Where in the standard are functions returning functions disallowed?


Where in the standard are functions returning functions disallowed? I understand they are conceptually ridiculous, but it seems to me that the grammar would allow them. According to this webpage, a "noptr-declarator [is] any valid declarator" which would include the declarator of a function:

int f()();

Regarding the syntax.

It seems to me that the syntax, as spelled out in [dcl.decl], allows

int f(char)(double)

which could be interpreted as the function f that takes a char and returns a function with same signature as int g(double).

1    declarator:
2       ptr-declarator
3       noptr-declarator parameters-and-qualifiers trailing-return-type
4    ptr-declarator:
5        noptr-declarator
6        ptr-operator ptr-declarator
7    noptr-declarator:
8        declarator-id attribute-specifier-seq opt
9        noptr-declarator parameters-and-qualifiers
10       noptr-declarator [ constant-expression opt ] attribute-specifier-seq opt
11       ( ptr-declarator )
12    parameters-and-qualifiers:
13       ( parameter-declaration-clause ) cv-qualifier-seqAfter

Roughly speaking, after 1->2, 2=4, 4->6, 4->6 you should have ptr-operator ptr-operator ptr-operator Then, use 4->5, 5=7, 7->8 for the first declarator; use 4->5, 5=7, 7->9 for the second and third declarators.


Solution

  • From [dcl.fct], pretty explicitly:

    Functions shall not have a return type of type array or function, although they may have a return type of type pointer or reference to such things. There shall be no arrays of functions, although there can be arrays of pointers to functions.

    With C++11, you probably just want:

    std::function<int()> f();
    std::function<int(double)> f(char);
    

    There is some confusion regarding the C++ grammar. The statement int f(char)(double); can be parsed according to the grammar. Here is a parse tree:

    grammar

    Furthermore such a parse is even meaningful based on [dcl.fct]/1:

    In a declaration T D where D has the form

        D1 ( parameter-declaration-clause ) cv-qualifier-seqopt
            ref-qualifieropt exception-specificationopt attribute-specifier-seqopt

    and the type of the contained declarator-id in the declaration T D1 is “derived-declarator-type-list T”, the type of the declarator-id in D is “derived-declarator-type-list function of (parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifieropt returning T”.

    In this example T == int, D == f(char)(double), D1 == f(char). The type of the declarator-id in T D1 (int f(char)) is "function of (char) returning int". So derived-declarator-type-list is "function of (char) returning". Thus, the type of f would be read as "function of (char) returning function of (double) returning int."

    It's ultimately much ado about nothing, as this is an explicitly disallowed declarator form. But not by the grammar.