Is my book's discussion of lambda return types wrong?

放肆的年华 提交于 2019-11-26 22:01:15

问题


My book says this:

Lambdas with function bodies that contain anything other than a single return statement that do not specify a return type return void.

but this:

auto f = []{
  int i=0; i++;
  return std::string("foo");
};
std::cout << f() << std::endl;

actually compiles and prints out "foo", but that lambda expr has more than just a single return statement so it should return void, because it does not manually specify "-> std::string" as a return type.

What's going on here?

I'm using Apple's compiler in the latest Xcode 4.6, based on Clang 3.2 it seems:

clang --version

Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) Target: x86_64-apple-darwin12.2.0 Thread model: posix


回答1:


The book accurately reflects the rules in draft n3290 of the Standard. Perhaps your compiler implemented a different draft.

In section 5.1.2p4, the draft reads

If a lambda-expression does not include a trailing-return-type, it is as if the trailing-return-type denotes the following type:

  • if the compound-statement is of the form { attribute-specifier-seqoptreturn expression ; } the type of the returned expression after lvalue-to-rvalue conversion, array-to-pointer conversion, and function-to-pointer conversion;
  • otherwise, void.

The syntactic construct attribute-specifier-seq may be alignas or the double-bracketed attributes. Not variable declarations.

Draft n3485, which followed publication of C++11 (i.e. it is work in progress toward C++1y), contains the same wording. I don't know if there was a different rule in some draft earlier than n3290.




回答2:


If you use popular compilers (gcc, Visual Studio), you usually don't need to specify return type as long as the compiler is able to determine it unambiguously - like in your example.

The following example shows a lambda, which requires explicit return type information:

auto lambda = [](bool b) -> float
    { 
        if (b) 
            return 5.0f; 
        else 
            return 6.0; 
    };

I asked Bjarne Stroustrup regarding this matter, his comment:

I do not know if C++11 allows the deduction of the return type is there are several return statements with identical return type. If not, that's planned for C++14.




回答3:


I am not sure of what to make from the quote in the question, but here is what the C++11 standard says about lambdas without declarator or return type:

If a lambda-expression does not include a lambda-declarator, it is as if the lambda-declarator were (). If a lambda-expression does not include a trailing-return-type, it is as if the trailing-return-type denotes the following type (5.1.2p4):

— if the compound-statement is of the form { attribute-specifier-seqopt return expression ; } the type of the returned expression after lvalue-to-rvalue conversion (4.1), array-to-pointer conversion (4.2), and function-to-pointer conversion (4.3);

— otherwise, void.




回答4:


Clang implements the proposed resolution to C++ core issue 975. That allows an arbitrary body for a lambda, with any number of return statements, and deduces the return value from the returned expression under the proviso that they must all produce the same type.

In C++14, this support is generalized further by N3638, which was voted into the working draft for the standard at the Bristol meeting of WG21.




回答5:


Draft n3485 indicates that if the compiler can unambiguously determine the return type it will allow for the lambda to not specify it.



来源:https://stackoverflow.com/questions/14738335/is-my-books-discussion-of-lambda-return-types-wrong

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!