如何检查禁用异常的构造函数的失败

how to check failure of constructor with exception disabled

本文关键字:异常 构造函数 失败 何检查 检查      更新时间:2023-10-16

在我们的代码库中,我们不使用c++异常,即gcc编译选项中的" -fno-exceptions "(请注意这是我们公司的政策,因此无需争论)。但是,在这种情况下,如何从标准库检查引发异常的构造函数的失败。我读了一些SO的帖子,但仍然没有明确的想法。例如,在c++11中,std::regex("pattern")可以抛出regex_error异常。如果我有以下代码:

class Wrapper {
public:
    bool create(std::string pattern) {
      try {
        m_regex = std::regex(pattern);
        m_state = true;
      } catch (std::regex_error& e) {
        //handle error case
        m_state = false;
      }
    }
private:
    std::regex m_regex;
    bool m_state;
}

注意:m_regex = std::regex(pattern);

将调用

explicit basic_regex(const CharT* s, flag_type f = std::regex_constants::ECMAScript)

可以抛出异常并移动赋值操作符

basic_regex& operator=(basic_regex&& __rhs) noexcept

现在,没有使用异常的选项,我们如何检查std::regex的构造函数是否失败?

class Wrapper {
public:
    create(std::string pattern) {
        m_regex = std::regex(pattern);
        // now, how to check? 
        // if (m_regex)?
        m_state = true;
    }
private:
    std::regex m_regex;
}

我没有在std::regex中找到任何可以指示失败的状态。

选项1:我可以假设如果regex构造函数失败,abort()将发生,那么以下语句m_state = true将不会被执行?我检查了一下,似乎abort()通常在启用异常的情况下发生,但没有使用catch。所以这是错误的。

选项2:我可以使用std::regex* ptr_regex = new std::regex("pattern"),并检查ptr_regex的空性?

这是一个尚未解决的问题,也是委员会的"低延迟"研究组第14研究组讨论的重大开放问题之一。

就标准而言,这是没有定义的。异常不是可选的,如果关闭异常会发生什么也没有说明。因此,标准库通常没有提供处理错误的替代方法。目前有一种趋势是在未来的提案中稍微减轻这一点。例如,当前的Filesystem TS具有非抛出的重载,它为所有可能抛出异常的函数返回一个错误代码。也许有可能以类似的方式为现有的标准库设施提供非抛出的替代方案,但这正是SG14试图弄清楚的。

到目前为止,重要的问题是:如果您的编译器在编译异常禁用时遇到throw(或try/catch),该怎么办?如前所述,该标准根本没有指定这一点,因此这里的任何解决方案都必然是不可移植的。您可能无法通过throw检测或从库指示的错误中恢复,因此,如果您不能预先排除将抛出异常的可能性,则可能希望避开抛出函数(因此,大多数标准库)。

希望这种情况在未来会有所改善。

创建一个库,其目的是包装需要异常的std实用程序。

此库在启用异常的情况下编译

它要么存储等价的optional<std::regex>(例如)。它提供了可能失败的构造函数(在库的.cpp材料中)调用构造函数,然后try/catch并将失败转换为空的regex

如果有其他可以抛出的操作,它将它们同样包装在具有错误返回路径的方法中。也许他们返回std::experimental::expected<T, error_information>

您必须小心处理该库和使用禁用异常的std库编译的代码之间的ODR和链接,因为它们之间的内联函数是不同的。我不知道如何避免这个问题的细节。在某些平台上,std库函数可能是动态链接的,您可能会以错误的方式加载编译错误的函数。我也不知道怎么解决这个问题。

从我从一个非常非常快速的谷歌中可以看出,一个库的膨胀和启用异常应该主要限制在该库的大小上。测试这个。