为什么在void函数中可以接受return throw std::exception()?

7

我不小心将throw语句粘贴到一个return之后,导致最终结果如下:

void DXManager::initialize(const std::shared_ptr<nae::Context>& ctx_ptr)
{
    // ...

    if (FAILED(result))
    {
        return throw std::exception("Failed to enumerate display mode list");
    }

    // ...
}

在注意到错误之前,我已经成功构建了解决方案,并且我很好奇哪个规范允许上述语法。


通过阅读cppreference.com(下面的注释),我发现

The throw-expression is classified as prvalue expression of type void. Like any other expression, it may be a sub-expression in another expression, most commonly in the conditional operator:

double f(double d)
  {
      return d > 1e7 ? throw std::overflow_error("too big") : d;
  }
  // ...

但我不确定它是否符合我的要求。


related/dupe: https://dev59.com/fXA75IYBdhLWcg3wRW2c - NathanOliver
1
@StoryTeller的答案完全正确,但关于来自cppreference.com的示例:该情况在标准[C++14: 5.16/2]中被明确允许:_如果第二个或第三个操作数具有void类型,则以下情况之一应成立:第二个或第三个操作数(但不能同时是两个)是throw表达式;结果是另一个的类型和值类别。_通常情况下,如果三元条件运算符的第二个和第三个操作数中仅有一个是void类型,则代码将无效,但throw是一个特殊情况。 - deltacrux
1个回答

6
好的,这是一段关于IT技术的翻译内容。在返回类型为void的函数中,return语句可以有一个void操作数。具体规定如下:[stmt.return]/2,其中,一个返回语句的expr-or-braced-init-list被称为其操作数。只有在返回类型为cv void的函数中,才能使用带有void操作数的返回语句。你自己发现了一个问题,即throw表达式的类型为void。这个规定是为了使编写通用代码更加顺畅。考虑以下情况:
template<typename T>
T foo() {
    return T();
}

上述规则(以及另一个定义void()的规则)使得即使针对void实例化,上述模板仍然有效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接