如果control-reach-of-body要返回nullopt会破坏什么?

时间:2017-01-30 21:10:58

标签: c++ c++17

C ++ 14为我们提供了自动返回类型推导,而C ++ 17有一个optional<T>类型模板(或类型构造函数,如果你愿意的话)。现在,true,optional存在于标准库中,而不是语言本身,但是 - 当控制到达正文末尾时,为什么不将它用作非void函数的返回值?我想是的:

optional<int> foo(int x)
{
    if (x > 0) return 2 * x;
}

应该是部分函数的完全有效且可编译的语法,返回optional<int>

现在,我知道这是一个疯狂的想法。我的问题不在于你是否喜欢,而是 - 假设委员会中的每个人都因为一些奇怪的原因而非常喜欢它。什么会破坏/冲突?

注意:当然,如果您指定了非可选的返回值,则无法生效,但这并不算作破损。

3 个答案:

答案 0 :(得分:3)

考虑以abort();结尾的函数或具有相同效果的自定义函数。如果编译器无法静态证明函数永远不会到达结束},这将迫使编译器生成死代码,因此与C ++的原则之一冲突,即零开销原则:你不会使用什么,你不会付钱。

答案 1 :(得分:3)

特殊套管std::optional在这里很荒谬。用户应该能够编写自己的一等等级std::optional

这意味着从函数的末尾掉下来需要使用某种魔法来确定隐含的返回值应该是什么。

最简单的魔法就是落后于return {};optional的情况下,这是nullopt。如果我正确阅读了我的标准,那么对于int,这是0,这与main的结束行为相符。

有缺点。首先,假设你有一个功能:

int foo(bool condition) {
  if (condition) return 7;
  custom_abort(); // does not return, but not marked up with `[[noreturn]]`
}

如果编译器无法证明return {};没有返回,这将导致编译器在custom_abort();之后写abort。这有一个成本(至少是二进制大小)。目前,编译器可以在foo之后排除从abort()返回所需的任何工作,并且假设 abort()将不会返回。

确实没有有效的程序会对此更改产生不同的行为,但之前未定义的行为会被定义,并且可能会产生成本。

我们可以采用稍微不同的方式来解决这个问题:

int foo(bool condition) {
  if (condition) return 7;
  custom_abort();
  this cannot be reached;
}

我们在C ++中添加了一个明确的“无法访问此位置”。

添加后,我们可以对不返回的代码路径发出警告,并在以后的标准中强制执行所有代码路径必须断言无法访问或必须返回的规则。

在语言的这种转换已经存在一个或两个标准周期之后,隐式return {};将是无害的,除了跳过返回的人不会发生标准化阶段。

答案 2 :(得分:2)

到目前为止,它是完整的未定义行为。这意味着没有有效的现有代码包含此构造。因此,添加明确定义的行为将不会破坏有效的代码。对于被破坏的代码,如果您的提案被接受,可能会或可能不会被破坏,但这几乎不会成为WG21的关注。

主要关注的是如何与其他语言功能进行交互。我没有看到与constexpr的冲突;从constexpr函数的末尾开始,将为空constexpr optional<T>[[noreturn]]属性显然毫无意义。 [[nodiscard]]属性会影响调用者,而不会影响实现。例外情况也不受影响。总的来说,这个提案似乎独立存在。

在向WG21提交的提案中,可能值得提出一个不那么激进的选择:使return;成为return optional<T>{};的有效替代