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.
Yes any function can return a function pointer.
Return Type − A function may return a value. The return_type is the data type of the value the function returns. Some functions perform the desired operations without returning a value. In this case, the return_type is the keyword void. Function Name − This is the actual name of the function.
Calling the function with () in a return statement executes the function, and returns whatever value was returned by the function.
Return Function Pointer From Function: To return a function pointer from a function, the return type of function should be a pointer to another function. But the compiler doesn't accept such a return type for a function, so we need to define a type that represents that particular function pointer.
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:
Furthermore such a parse is even meaningful based on [dcl.fct]/1:
In a declaration
T D
whereD
has the form
D1
( parameter-declaration-clause ) cv-qualifier-seqopt
ref-qualifieroptexception-specificationoptattribute-specifier-seqopt
and the type of the contained declarator-id in the declarationT D1
is “derived-declarator-type-listT
”, the type of the declarator-id inD
is “derived-declarator-type-list function of (parameter-declaration-clause ) cv-qualifier-seqoptref-qualifieropt returningT
”.
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.
With C++11 (but not previous versions of C++) you can not only return C-like function pointers, but also C++ closures, notably with anonymous functions. See also std::function
The standard disallows (semantically, not syntactically - so it is not a question of grammar ; see Barry's answer for the citation) returning functions (and also disallow sizeof
on functions!) but permits to return function pointers.
BTW, I don't think that you could return entire functions. What would that mean? How would you implement that? Practically speaking, a function is some code block, and its name is (like for arrays) a pointer to the start of the function's machine code.
A nice trick might be to build (using mechanisms outside of the C++ standard) a function at runtime (and then handling its function pointer). Some external libraries might permit that: you could use a JIT library (e.g. asmjit, gccjit, LLVM ...) or simply generate C++ code, then compile and dlopen & dlsym it on POSIX systems, etc.
PS. You are probably right in understanding that the C++11 grammar (the EBNF rules in the standard) does not disallow returning functions. It is a semantic rule stated in plain English which disallows that (it is not any grammar rule). I mean that the EBNF alone would allow:
// semantically wrong... but perhaps not syntactically
typedef int sigfun_T(std::string);
sigfun_T foobar(int);
and it is for semantics reasons (not because of EBNF rules) that a compiler is rightly rejecting the above code. Practically speaking, the symbol table matters a lot to the C++ compiler (and it is not syntax or context-free grammar).
The sad fact about C++ is that (for legacy reasons) its grammar (alone) is very ambiguous. Hence C++11 is difficult to read (for humans), difficult to write (for developers), difficult to parse (for compilers), ....
using namespace std;
auto hello()
{
char name[] = "asdf";
return [&]() -> void
{
printf("%s\n", name);
};
}
int main()
{
hello()();
auto r = hello();
r();
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With