Is there a reason on not allowing lambdas to deduc

2020-02-14 02:40发布

Taken from the C++0x FDIS (n3290):

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:

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

Why doesn't the standard allow the compiler to analyse the compound-statement and determine the return type based on the first found return statement?

I can't see any reason to not allow this, but maybe I'm overlooking something.

Example:

int main(){
  // compiler: nope.jpg
  auto l = []{
    // one computation
    // another computation
    // yet another one!
    return something;
  }
}

Edit: Please no "because the standard says so" answers. :)

4条回答
Fickle 薄情
2楼-- · 2020-02-14 03:11

There's no technical reason for this. IIRC it was already implemented by the GCC C++ maintainer and he said it's trivial to implement.

The committee is very conservative about accepting features into the Standard so they went with this simple form of deduction and will later hopefully accept a more powerful form. See the reason for rejection on US 30 comment.

DR 975 is already marked "ready" so chances are good it will be accepted.

查看更多
一纸荒年 Trace。
3楼-- · 2020-02-14 03:18

I believe this is not a restriction but an allowance to leave out -> decltype(expression) when the body is just return expression. It is pretty obvious what the return type is in that case.

Your suggestion requires a lot more work for the compilers and a lot more rules for us, the programmers. Does it buy us much?

查看更多
ら.Afraid
4楼-- · 2020-02-14 03:22

Why doesn't the standard allow the compiler to analyse the compound-statement and determine the return type based on the first found return statement?

In my opinion, reasons are inheritance, implicit typecast to void* and 0 typecasted to int, which makes it difficult for compiler implementers to deduce type from the first return statement. See the below examples:

// "B" is a derived by "D"
int main(){
  auto l = []{
    return (D*)(...);  // should it be "D*" (derived)
    // computation
    return (B*)(...);  // no it should be "B*" (base)
  }
}

Second,

int main(){
  auto l = []{
    return (int*)(...);  // should it be "int*"
    // computation
    return (void*)(...);  // no it has to be "void*"
  }
}

Third one,

int main(){
  auto l = []{
    return 0;  // should it be "int"
    // computation
    return (double)(...); // no it has to be "double"
  }
}

Also there is one more reason related to giving a compilation error message, when two unrelated return are found:

int main(){
  auto l = []{
    return TYPE1;
    // computation
    return TYPE2;
  }
}

Now, question would arise that what useful compiler message should be printed to user ? The error message has to be only for one of the return statements. Which return to choose ?

查看更多
不美不萌又怎样
5楼-- · 2020-02-14 03:27

I guess it's because of this kind of code :

void foo( bool k )
{
    auto call= [](){ if( k ) return 42; else return 'c'; };  // what is the return type?
    call();
}

Here the return type could be int or char. As each one of those types is implicitely convertible to the other, that's too ambiguous for the compiler to guess what is the return type. So to avoid confusion or to avoid the compiler implementation to decide witch type it should be, the comitee simply tell that this should produce an error( a diagnostic) allowing the programmer to specify wich type was required.

So it's just to make sure compilers will not compile code that is too ambiguous to allow return type guessing.

查看更多
登录 后发表回答