Как объявить лямбда-оператор () как noreturn?

Как можно operator() лямбда объявляется как noreturn ?

Ideone принимает следующий код:

#include <cstdlib>
int main() {
[]() [[noreturn]] { std::exit(1); }();
return 0;
}

Clang 3.5 отклоняет это с:

error: 'noreturn' attribute cannot be applied to types

Вы можете попробовать это в Godbolt: http://goo.gl/vsuCsF

Какой из них прав?

Обновить: соответствующие стандартные разделы выглядят как 5.1.2.5, 7.6.3, 7.6.4, но после прочтения мне все еще не ясно на 100% (i) каково правильное поведение, (ii) как пометить оператора () лямбда как noreturn,

14

Решение

Clang это правильно. Атрибут может относиться к объявленной функции или к ее типу; два разные. [[noreturn]] должен относиться к самой функции. Разницу можно увидеть в

// [[noreturn]] appertains to the entity that's being declared
void f [[noreturn]] ();    // §8.3 [dcl.meaning]/p1:
// The optional attribute-specifier-seq following a
// declarator-id appertains to the entity that is declared."[[noreturn]] void h ();    // §7 [dcl.dcl]/p2:
// "The attribute-specifier-seq in a simple-declaration
// appertains to each of the entities declared by
// the declarators of the init-declarator-list."
// ill-formed - [[noreturn]] appertains to the type (§8.3.5 [dcl.fct]/p1:
// "The optional attribute-specifier-seq appertains to the function type.")
void g () [[noreturn]] {}

Действительно, если вы скомпилируете это в g ++, это скажет вам, что

warning: attribute ignored [-Wattributes]
void g () [[noreturn]] {}
^
note: an attribute that appertains to a type-specifier is ignored

Обратите внимание, что он не выдает предупреждение о том, что g() на самом деле возвращается.

С «Атрибут спецификатор-сл в лямбда-описатель относится к типу соответствующего оператора вызова функции или шаблона оператора «(§5.1.2 [expr.prim.lambda] / p5), а не к самому шаблону оператора / оператора, вы не можете использовать [[noreturn]] там. В более общем смысле язык не позволяет вам применить атрибут к operator () самой лямбды.

20

Другие решения

Таким образом, лямбда-делькаратор имеет следующую грамматику черновик стандартного раздела C ++ 5.1.2 Лямбда-выражения:

( parameter-declaration-clause ) mutableopt exception-specificationopt attribute-specifier-seqopt trailing-return-typeopt

и атрибут noreturn действительно является действительным Атрибут спецификатор-сл так что с точки зрения грамматики я не вижу ограничения из раздела 7.6.3 Атрибут норетурн это говорит (Акцент шахты идет вперед):

[…] Атрибут может быть применен к идентификатору объявления в функции
декларация. […]

который, по-видимому, не запрещает ваше использование, но предполагает, что это запрещено. Если мы посмотрим на раздел 7.6.4 Несет атрибут зависимости это говорит:

[…] Атрибут может быть применен к объявителю-идентификатору
объявление параметра в объявлении функции или лямбда[…]

тот факт, что он явно включает случай лямда 7.6.3 предназначен для исключения лямбд и, следовательно, clang было бы правильно. В качестве примечания, Visual Studio также отклоняет этот код.

4

[C++11: 7.6.3/1]: Атрибут-маркер noreturn указывает, что функция не возвращает. Это должно появиться не более одного раза в каждом список атрибутов и нет атрибут-аргумент придаточного должен присутствовать. Атрибут может быть применен к описатель-идентификатор в объявлении функции. Первое объявление функции должно указывать noreturn атрибут, если любое объявление этой функции определяет noreturn приписывать. Если функция объявлена ​​с noreturn атрибут в одной единице перевода и та же функция объявляется без noreturn атрибут в другой единице перевода, программа плохо сформирована; Диагностика не требуется.

Я допускаю, что эта формулировка, как она есть, не запрещает появление атрибута в другом месте, но в сочетании с отсутствием каких-либо доказательств в стандарте для него, я не думаю, что это предназначено для работы с лямбда-декларациями.

Поэтому Clang будет прав.

Это может или не может говорить, что было предложение патча к Clang, чтобы позволить стиль GCC noreturn атрибуты на лямбдах, но не стандартная форма.

К сожалению, эта функция не включена в Список расширений GCC, так что я не могу точно увидеть, что здесь происходит.

2
По вопросам рекламы [email protected]