【问题标题】:Programmatically determine whether exceptions are enabled以编程方式确定是否启用异常
【发布时间】:2011-09-23 03:22:54
【问题描述】:

大多数 C++ 编译器允许禁用异常。有没有办法从代码中确定它而不使用编译器特定的预处理器宏,例如 MSVC 的 _CPPUNWIND?理想情况下在编译时。

【问题讨论】:

  • 如果这是一个 autoconf 系统,只需让 autoconf 尝试使用 try / catch 编译某些东西,看看它是否还能编译。视觉工作室?不确定,你可能被宏卡住了。
  • 有趣的问题,但这些信息有什么用?
  • 很难看出这一点。 std::bad_alloc 和朋友是真实的,无论您是否启用异常处理。没有启用异常处理的“让我们做一些合理的事情”的角度是一个非常模糊的角度。他们以一种或另一种方式轰炸你的程序。
  • @Hans:在许多情况下,允许异常“轰炸你的程序”是可以接受的风险。例如,99% 的视频游戏会禁用性能异常。
  • @Kerrek SB:我正在寻找重新设计一个库的好方法,该库既可用于启用异常的项目,也可用于禁用异常的项目。 Boost 为此目的有自己的宏 - 我正在寻找避免预处理器的东西。

标签: c++ exception metaprogramming


【解决方案1】:

由于WG21 in 2014,有一个推荐使用的宏

__cpp_exceptions

如果支持异常并且编译器符合 C++98,它将具有值 199711。其他similar feature macros are shown here.

【讨论】:

  • 我观察到的一个挑战是 MSVC 不使用这些,如果您禁用异常/rtti,这些宏是未定义的,因此很难区分两者(即编译器是否支持 __cpp_exceptions 和异常被禁用或编译器不支持 __cpp_exceptions & 我们应该使用编译器特定的逻辑)。
【解决方案2】:

我根本不会为这个决定增加运行时的负担。相反,我会构建两个库:

libfoo.a
libfoo_exc.a

然后我会让我的configure 脚本确定我们是否有异常,并像这样设置 Makefile:

ifeq($HAVE_EXCEPTIONS, 1)
  foolib=foo_exc
else
  foolib=foo
endif

libs=$(libs) -l$(foolib)

$(TARGET): $(OBJECTS)
    $(CXX) -o $(TARGET) $(OBJECTS) $(LDFLAGS) $(LIBS)

要确定您是否有异常,您可以简单地尝试使用 cmets 中建议的简单的 try/catch 块构建一个小型测试程序。

要真正构建你的库,只需编写条件代码:

#if HAVE_EXCEPTIONS > 0
/* ... */
#else
/* ... */
#endif

然后构建两个库,一个使用-DHAVE_EXCEPTIONS=0,一个使用-DHAVE_EXCEPTIONS=1 或类似的东西。

这样您就没有运行时开销,并且您的客户可以使用他们喜欢的任何库。

【讨论】:

    【解决方案3】:

    没有。异常是 C++ 的一部分。某些编译器允许您禁用它们的事实是完全不相关的,并且标准不会让您检测它们是否已启用 - 就它而言,它们始终处于启用状态。如果您想了解特定于实现的行为,唯一的方法就是询问实现。

    【讨论】:

    • +1。如果一开始就有缺陷,这似乎是OP的问题。它可以重新表述为:“我可以以与编译器无关的方式检测编译器特定的行为吗?”
    • @Andre:你可以随意改写,但我相信我在问一个具体而实际的问题。
    猜你喜欢
    • 2013-08-12
    • 2011-11-27
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 2011-02-13
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    相关资源
    最近更新 更多