当使用lambda进行变量的复杂初始化时,如何处理从内部抛出的lambda异常之外的内容?

我正在使用lambdas初始化一些const变量,如核心c ++准则here中所述。简而言之,这个成语看起来像这样

const auto a = [&]() {
    MyType a;
    // complex initialization
    return a;
}();

当初始化可能引发只能在lambda之外处理的异常时,就会出现问题,例如,因为它必须使函数提前返回。我希望能够做类似这样的事情

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块之后可用。

我可以重构该函数,以便所有依赖于对象的成功初始化的代码都在try块内,但这会随着多个对象的初始化而急剧扩展。

try {
    const auto a = ...;
    try {
        const auto b = ...;
        try...
        catch...
    }
    catch {...} {
        ...;
    }
catch {...} {
    ...;
}

另一方面,将try-catch块移入lambda内会限制我可以做的处理。例如,据我所知,它不允许我立即returnbreakcontinue。几乎感觉上逻辑上的解决方案似乎是将分配与try块(例如const auto a = try [&]()...)交织在一起,但是似乎不被这种支持所支持。我是否正确,因为不支持此操作?如果是,是否存在另一个已知习语会导致我需要的行为?

注意:我要求的情况是变量为const很重要,或者不可能进行默认构造并不能赋值,因此在try块之外并在内部分配值的默认构造的明显解决方案这是不可行的。

speedlee 回答:当使用lambda进行变量的复杂初始化时,如何处理从内部抛出的lambda异常之外的内容?

老实说,这与可能引发的简单初始化没有什么不同。尽量不要对您的例外进行微观管理。它们的功能在于使您可以自由编写代码,而不必担心每个语句的错误。将完成一项完整工作(或操作)的所有代码放入try{}catch(){}中。异常应该中止整个过程,而不仅仅是一次初始化。

try
{
    const auto a = [&]() {
        MyType a;
        // complex initialization
        return a;
    }();

    const auto b = "something else that may throw"s;

    const auto c = a_throwing_function();

    // Now do stuff with a,b and c safe in the knowledge that
    // they are properly constructed and valid

    // ... etc ...
}
catch(std::exception const& e)
{
    // abort the entire operation
}
本文链接:https://www.f2er.com/3165588.html

大家都在问