C++ function returning function

后端 未结 7 570
南笙
南笙 2020-12-24 12:13

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. Acco

相关标签:
7条回答
  • 2020-12-24 12:16
    using namespace std;
    
    auto hello()
    {
        char name[] = "asdf";
        return [&]() -> void
        {
            printf("%s\n", name);
        };
    }
    
    int main()
    {
        hello()();
        auto r = hello();
        r();
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-24 12:21

    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.

    0 讨论(0)
  • 2020-12-24 12:26

    The formal grammar of C actually disallows returning functions but, one can always return a function pointer which, for all intents and purposes, seems like what you want to do:

      int (*getFunc())(int, int) { … }
    

    I am fixated in saying, the grammar, is a more fundamental explanation for the lack of support of such feature. The standard's rules are a latter concern.

    If the grammar does not provide for a way to accomplish something, I don't think it matters what the semantics or the standard says for any given context-free language.

    0 讨论(0)
  • 2020-12-24 12:27

    in kinda sense,function_pointer is funciton its self,
    and "trailing return type" is a good and hiding thing in c++11,i will rather write like this:

    #include<iostream>
    
    
    
    auto return0(void)->int
    {return 0;}
    auto returnf(void)->decltype(&return0)
    {return &return0;}
    
    
    
    /*Edit: or...
    auto returnf(void)->auto (*)(void)->int
    {return &return0;}
    //that star means function pointer
    */
    
    
    
    
    auto main(void)->int
    {
        std::cout<<returnf()();
        return 0;
    }
    

    (if type unmatch,try apply address operator "&")
    look,so much of sense.

    but down side of this is that "auto" thing in head of function,
    that`s non-removable and no type could match it (even lambda could match template type std::function<>) but if you wish,macro could do magic(sometime curse) to you

    #define func auto
    
    0 讨论(0)
  • 2020-12-24 12:28

    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), ....

    0 讨论(0)
  • 2020-12-24 12:29

    Unless you are returning a pointer or reference to a function which is ok, the alternative is returning a copy of a function. Now, think about what a copy of a function looks like, acts like, behaves like. That, first of all would be an array of bytes, which isn't allowed either, and second of all those bytes would be the equivalence of a piece of code literally returning a piece of code....nearly all heuristic virus scanners would consider that a virus because there would also be no way to verify the viability of the code being returned by the runtime system or even at compile time. Even if you could return an array, how would you return a function? The primary issue with returning an array (which would be a copy on the stack) is that the size is not known and so there's no way to remove it from the stack, and the same dilemma exists for functions (where the array would be the machine language binary code). Also, if you did return a function in that fashion, how would you turn around and call that function?

    To sum up, the notion of returning a function rather than a point to a function fails because the notion of that is a unknown size array of machine code placed (copied) onto the stack. It's not something the C or C++ was designed to allow, and with code there is now way to turn around and call that function, especially i you wanted to pass arguments.

    I hope this makes sense

    0 讨论(0)
提交回复
热议问题