如何向编译器表明函数总是抛出?

Ass*_*vie 9 c++ exception visual-c++

当调用始终从返回值的函数抛出的函数时,编译器经常警告并非所有控制路径都返回值.合法的.

void AlwaysThrows() { throw "something"; }

bool foo()
{
    if (cond)
        AlwaysThrows();
    else
        return true; // Warning C4715 here
}
Run Code Online (Sandbox Code Playgroud)

有没有办法告诉编译器AlwaysThrows的功能是什么?

我知道我可以throw在函数调用后添加另一个:

{ AlwaysThrows(); throw "dummy"; }
Run Code Online (Sandbox Code Playgroud)

而且我知道我可以明确地禁用警告.但我想知道是否有更优雅的解决方案.

And*_*zos 16

使用Noreturn属性.这在最新版本的C++标准第三版ISO/IEC 14882:2011的"7.6.3 Noreturn属性[dcl.attr.noreturn]"一节中指定.

标准示例:

[[ noreturn ]] void f()
{
    throw "error";
}
Run Code Online (Sandbox Code Playgroud)


Jes*_*all 6

您可以在调用AlwaysThrows()之后添加一个虚拟返回语句,并在注释中解释它为什么存在.当您调用的函数始终为exit()s或abort()时,这也很有用.


小智 5

当然,有一个问题是你为什么要首先编写这样的代码.显而易见的答案是,AlwaysTrows()实际上是某种错误报告功能.在我自己的代码中,我实际上使用宏来执行错误报告,因为它允许我执行字符串格式化并获取standatd __LINE____FILE__宏.宏看起来大致如下:

#define ATHROW( msg )                                               \
{                                                                   \
    std::ostringstream os_;                                         \
    os_ << msg;                                                     \
    throw ALib::Exception( os_.str(), __LINE__, __FILE__ );         \
}
Run Code Online (Sandbox Code Playgroud)

其中异常构造函数执行任何额外的格式化,额外的日志记录等.这样做的副作用当然是编译器可以看到抛出异常,所以当我说的话时:

int f() int val ) {
   if ( val >= BADVALUE ) {
       ATHROW( "Invalid value " << val << " for val" );
   }
   else {
       return val / 3;
   }
}
Run Code Online (Sandbox Code Playgroud)

然后我不会得到关于f()没有返回值的警告.


Mic*_*ael 4

通过 Visual C++,您可以使用__declspec(noreturn).

  • 如下所述,自 C++11 起 `[[noreturn]]` (4认同)