【问题标题】:Why is return throw std::exception() accepted in a void function?为什么在 void 函数中接受 return throw std::exception()?
【发布时间】:2018-08-28 13:44:51
【问题描述】:

我错误地将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(在 Notes 下),我明白了

throw 表达式被归类为 void 类型的纯右值表达式。与任何其他表达式一样,它可能是另一个表达式中的子表达式,最常见于条件运算符中:

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

但我不太确定这是我要找的东西。

【问题讨论】:

  • @StoryTeller 对您的问题的回答是完全正确的,但关于 cppreference.com 中的示例:标准 [C++14: 5.16/2] 明确允许这种情况:如果第二个或第三个操作数的类型为 void,应满足以下条件之一: 第二个或第三个操作数(但不是两者)是 throw 表达式;结果是另一个的类型和值类别。 通常,如果三元条件的第二个和第三个操作数中只有一个是 void 类型,则代码将无效,但 throw 是一种特殊情况。

标签: c++ visual-studio exception return prvalue


【解决方案1】:

嗯,这是因为返回void的函数中的return语句可以有一个void操作数:

[stmt.return]/2

return 语句的 expr-or-braced-init-list 称为它的操作数 [...] 带有 void 类型操作数的 return 语句只能用于 返回类型为 cv void 的函数。

正如您自己发现的那样,throw 表达式的类型为 void。这条规定是为了使编写通用代码更顺畅。考虑一下:

template<typename T>
T foo() {
    return T();
}

上述规则(以及定义void() 的另一个规则)使上述模板即使在为void 实例化时也有效。

【讨论】:

    猜你喜欢
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 2018-10-06
    • 2015-11-06
    • 2013-01-13
    • 2014-11-19
    相关资源
    最近更新 更多