С++ 11 ограничений на тип возврата лямбда

Я читаю здесь на cppreference о том, как выводится тип возвращаемого значения лямбда С++ 11:

если тело состоит из одного оператора return, возвращаемый тип - это тип возвращаемого выражения (после значения rvalue-to-lvalue, array-to-pointer или неявного преобразования функции-к-указателю)

Итак, я думаю, это означает, что лямбда может иметь только один оператор возврата. Но почему он работает с несколькими возвращающими операторами?

Этот компилирует для обоих компиляторов:

auto f = [] (bool c1, bool c2) {
    if (c1) return 1;
    if (c2) return 2;
    else    return 3;
};

Ответ 1

Это немного неточно. [Expr.prim.lambda]/4:

Если лямбда-выражение не содержит лямбда-декларатора, оно как будто лямбда-декларатор (). Если лямбда-выражение не включают тип возвращаемого типа возврата, это как если бы trailing-return-type обозначает следующий тип:

  • если составной оператор имеет вид

    { выражение-specifier-seq optreturn выражение ; }

    тип возвращаемого выражения после lvalue-to-rvalue преобразование (4.1), преобразование матрицы в указатель (4.2) и преобразование функции в указатель (4.3);

  • в противном случае void.

Таким образом, возвращаемый тип выводится только в том случае, если весь элемент выражения лямбда состоит только из одного единственного оператора return.

Как GCC, так и Clang не соответствуют стандарту в этом случае, поскольку они выдают ошибку сообщение тогда и только тогда, когда два оператора return приводят к несогласованным выводам. Это связано с тем, что они уже реализовали стандарт С++ 14, который вычитает возвращаемый тип даже при наличии нескольких операторов return и/или нескольких других утверждений. [expr.prim.lambda]/4 указывает, что

Тип возврата лямбда auto, который заменяется на trailing-return-type, если предоставляется и/или выводится из операторов return, как описано в 7.1.6.4.

§7.1.6.4/9

Если функция с объявленным типом возврата, содержащая местозаполнитель тип имеет несколько операторов return, тип возврата выводится для каждый return. Если выведенный тип не является одинаковым в каждом вычет, программа плохо сформирована.

Ответ 2

Он работает с вашим примером, потому что все операторы return возвращают значения одного и того же типа. Но попробуйте изменить второй return на другой тип, например:

auto f = [] (bool c1, bool c2) {
    if (c1) return 1;
    if (c2) return "";
    else    return 3;
};

Компиляция с помощью clang++ приводит к следующей ошибке:

main.cpp:3:13: error: return type 'const char *' must match previous return type 'int' when lambda expression has unspecified explicit
      return type
    if (c2) return "";
        ^
1 error generated.