Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 编译时检测不应该抛出但仍然抛出的函数(noexcept或其他方法)_C++_Exception Handling - Fatal编程技术网

C++ 编译时检测不应该抛出但仍然抛出的函数(noexcept或其他方法)

C++ 编译时检测不应该抛出但仍然抛出的函数(noexcept或其他方法),c++,exception-handling,C++,Exception Handling,我知道这只是提供信息,gcc/clang不会触发此代码段的任何警告/错误: void foo() noexcept { throw 1; } int main() { foo(); return 0; } 那么-有没有一种方法或技术可以标记一个函数不抛出任何东西,并在实现抛出时从编译器实际获得编译时警告/错误 一个简单的用例——我有一个框架,它公开了一组客户端插件应该实现的接口,然后该框架从共享对象加载插件,通过工厂实例化接口,并调用接口方法。我更希望在调用过程中不会在库边界上抛

我知道这只是提供信息,gcc/clang不会触发此代码段的任何警告/错误:

void foo() noexcept
{
  throw 1;
}

int main()
{
  foo();
  return 0;
}
那么-有没有一种方法或技术可以标记一个函数不抛出任何东西,并在实现抛出时从编译器实际获得编译时警告/错误

一个简单的用例——我有一个框架,它公开了一组客户端插件应该实现的接口,然后该框架从共享对象加载插件,通过工厂实例化接口,并调用接口方法。我更希望在调用过程中不会在库边界上抛出异常,因此我希望将插件实现的接口中的所有函数标记为不抛出,而不是依赖于包含
try
/
catch
块的实现。是否有任何通用技术/替代解决方案

我也知道,没有编译时检查可以检测在运行时可能发生的由于无效数据而出现的潜在结构化异常,但是否存在至少用于C++异常的工作?

编辑

感谢Jason的评论,我检查了函数指针发生的情况,也有点失望——至少在下面的代码段中,gcc没有:

void foo() noexcept
{
  throw 1;
}

void bar() noexcept(false)
{
}

int main()
{
  void (*safe_function_one)() noexcept  = &foo;  
  void (*safe_function_two)() noexcept  = &bar;  
  return 0;
}

请记住,noexcept是编译器的一个线索,它不需要提供适当的机制来展开此特定函数中的堆栈帧(以防止异常),从而允许它进行更多的优化。如果仍然抛出异常,则可能无法进行正确的恢复

std::如果没有例外,则移动是实现无例外的关键。noexcept用于具有移动语义的特定情况,如下所述

正如您所指出的,在编译时无法确定无效数据。虽然在函数的根作用域中检测“throw”很简单,但分析可能从该函数调用的所有可能的代码路径以确定是否引发异常则需要更多的工作。我怀疑所有的编译器都在他们的列表中列出了这一点,并且正在努力寻找解决方案,但是noexcept从来就不是一个保证,所以我怀疑这是一个相当激烈的争论

现在,您可能希望使用noexcept来修饰函数,并允许编译器生成更快的代码,并且非常强烈地传达抛出异常将产生不稳定行为的信息。然而,编译器无论如何都可以执行其中一些优化,即使没有异常。例如,编译器可以很容易地确定许多内联函数是很好的候选函数

编辑:
正如@Creris正确指出的那样,如果无法找到匹配的异常处理程序(这是非常不可取的),将立即调用std::terminate(),但这当然不会阻止开发人员在这些情况下使用throw

我想可能有关系。@Caninonos很棒的发现,这是我一直在寻找的方向,谢谢:)记住,函数可以在运行时绑定,所以编译器不能保证编译时
noexcept
。@Jason-这对我来说有点失望,我刚刚发现,您不能在函数指针定义中使用
noexcept
,至少检查指针是否兼容。至少clang抱怨过,gcc没有。实际上,对于Scott Meyers是否尽可能使用
noexcept
,存在着激烈的争论,因为这可能是错误的保证。我只在我个人知道不会抛出的函数上使用它。将其添加到接口无法强制实现者不会抛出异常,因此根据情况(例如函数指针),这可能不是一件安全的事情。是的,我在问题中已经说过,我知道在编译时进行完全检测是不可能的,
noexcept
更像是一种装饰。我只是希望任何人都会出现一个神秘的gcc或叮当开关,它至少会产生警告:)“如果搜索匹配的异常处理程序时留下一个标记为noexcept或noexcept(true)的函数,就会立即调用std::terminate。”因此,没有办法从noexcept抛出function@Creris好的,我澄清了标题,问题在于编译时检测,而不是运行时结果。感谢您的评论,我认为我已经清楚地表达了意图,但显然我错了。@Creris,您是对的,如果未捕获一个抛出,将调用std::terminate(),这当然不会阻止使用抛出。试试看。@nullptr,感谢移动构造函数上的链接,这很有趣,+1来自我