2014-03-28 5 views
0

Я ничего не могу найти о бросании исключений при создании объекта закрытия.Может ли C++ лямбда-выражение бросить?

Это не обращая внимания, что это выражение может бросить во время копирования конструкции вектора:

auto v = std::vector<int>(1000000); 
[v]{}; 

Но как насчет пустых или «по ссылке» списки захвата, как это:

[&]{}; 

Я говорю только о конструкции объекта закрытия сейчас. Вызов не интересен.

Я прочитал 5.1.2 Lambda expressions [expr.prim.lambda], но ничего особенного не нашел о гарантии nothrow.

+0

Как любая функция _'normal'_, вызванная функцией лямбда, может бросать, что вы подозреваете для лямбда-функций? –

ответ

4

В соответствии со стандартом (draft n3337), §5.1.2/3:

тип лямбда-выражения (который также является тип объекта закрытия) является уникальным, безымянная несращение тип класса - называется типом замыкания - свойства которого описаны ниже. Этот тип класса не является агрегатом (8.5.1). Тип замыкания объявляется в области наименьшего блока, области видимости класса или пространства имен , содержащей соответствующее лямбда-выражение.

В двух словах выражение лямбда в конечном счете создает анонимный тип (известный только компилятору), содержащий переменные-члены, которые сохраняют значения, указанные в списке захвата. Так представьте, что вы видели, класс, который выглядел так:

class __IgnoreMe__ 
{ 
    std::vector<int>& _v; 

public: 
    __IgnoreMe__(std::vector<int>& v) 
     : _v(v) 
    { 
    } 

    void operator()() 
    { 
    } 
}; 

(Примечание: это не точно, как выглядит класс, созданный компилятором стандарт устанавливает специальные требования для сгенерированных классов, которые я». ве опущены для краткости)

Теперь представьте себе, вы экземпляр этого класса, как это:.

auto v = std::vector<int>(1000000); 
auto my_lambda = __IgnoreMe__(v); 

Может конкретизацией my_lambda бросить исключение? Если это так, то построение объекта замыкания может вызвать исключение. (Он не может, в этом случае.)

Что касается предоставления nothrow гарантий, стандарт не требует компиляторов с учетом этого, но это не предотвратить им делать это либо. Конец §5.1.2/3 гласит:

Реализация может определить тип закрытия по-другому от того, что описано ниже, если это не изменяет наблюдаемого поведения из программы иначе, чем изменение:

- размер и/или выравнивание типа закрытия,

- является ли тривиальным копируемым типом закрытия (пункт 9),

- тип закрытия, является ли классом стандартного макета (пункт 9), или

- является ли тип замыкания классом POD (раздел 9).

+0

Обратите внимание, что лямбда не нуждается в *, чтобы иметь ссылочные элементы. В некоторых реализациях используется только один указатель на стек стека вместо N ссылок. – dyp

+0

Nitpick - сгенерированный 'operator()' является 'const', если вы не отметите lambda' mutable'. – Praetorian

+0

Спасибо, что вызвали их. Я целенаправленно отказался от некоторых деталей (включая 'delete'd constructors), но хорошо указать на это, чтобы читатели знали. Я отредактировал ответ, чтобы включить отказ от ответственности. – Lilshieste

Смежные вопросы