Я использую лямбда-выражения для инициализации некоторых const
переменных, как описано в основных рекомендациях по c ++ здесь . Короче говоря, идиома выглядит следующим образом:
const auto a = [&]() {
MyType a;
// complex initialization
return a;
}();
Проблема возникает, когда инициализация может вызвать исключение, которое может быть обработано только за пределами лямбды, например, из-за того, что оно должно вызвать преждевременный возврат функции. Я хочу иметь возможность делать что-то похожее на это
try {
const auto a = [&]() {
MyType a;
// complex initialization
return a;
}();
}
catch { /* doesn't matter what */ } {
// Somehow handle it
// then return or throw
}
// use a
, за исключением того, что я хочу, чтобы объект мог использоваться после блока try-catch, когда исключение не выдается.
Iмог бы реорганизовать функцию так, чтобы весь код, который зависит от успешной инициализации объекта, находился внутри блока try
, но это ужасно масштабировалось с несколькими объектами для инициализации.
try {
const auto a = ...;
try {
const auto b = ...;
try...
catch...
}
catch {...} {
...;
}
catch {...} {
...;
}
С другой стороны, перемещая попытку-catch блок внутри лямбда ограничивает то, что я могу сделать, чтобы справиться с этим. например, это не позволяет мне мгновенно return
, break
или continue
, насколько я могу судить. Похоже, что логическим решением было бы чередовать назначение с блоком try (например, const auto a = try [&]()...
), но, похоже, это не поддерживается языком. Правильно ли я в том, что это не поддерживается, и если да, то есть ли другая известная идиома, которая привела бы к нужному мне поведению?
Примечание: я спрашиваю о ситуациях, в которых важно, чтобы переменная была const
или если конструкция по умолчанию с последующим присваиванием невозможна, поэтому очевидное решение конструирования по умолчанию вне блока try и присвоения значения внутри него нежизнеспособно.