Является ли законным использовать значение const, записанное в лямбда в качестве аргумента шаблона?

Рассмотрим следующий код, предоставленный коллегой:

#include <array>
#include <string>

int main() {
    const int size = 4;
    return [size]() {
      std::array<std::string, size> a; // *
      return a.size();
    }();
}

Он принимается Clang 5.0.0, но отклоняется GCC 7.2 с сообщением об ошибке для выделенной строки:

error: '__closure' is not a constant expression

Какой компилятор прав?

Ответы

Ответ 1

Это правило фактически интуитивно понятное: любое вхождение переменной, которая не требует захвата, относится к исходной переменной. [expr.prim.lambda]/11:

Каждое id-выражение в составной формуле лямбда-выражение, которое является нечетным использованием объекта, захваченного копией, преобразуется в доступ к соответствующему неназванному элементу данных тип закрытия. [Примечание: Идентификатор, не являющийся неприемлемым относится к исходному объекту, никогда не относится к типу замыкания. [...] - примечание к концу]

Ясно, что объявленная переменная size может использоваться в постоянных выражениях, поэтому Clang прав.