C++ 中的抛出和三元运算符

发布于 2024-12-12 14:50:53 字数 284 浏览 0 评论 0原文

以下代码可以使用 G++ 4.6.1 进行编译,但不能使用 Visual Studio 2008

return (m_something == 0) ? 
    throw std::logic_error("Something wrong happened") : m_something;

进行编译。事实上,Visual Studio 编译器会发生内部崩溃。

我想知道这是否是标准 C++,为什么它不能用 Visual Studio 编译,但可以用 G++ 编译?

The following code compiles with G++ 4.6.1, but not with Visual Studio 2008

return (m_something == 0) ? 
    throw std::logic_error("Something wrong happened") : m_something;

The fact is the Visual Studio compiler performs an internal crash.

I want to know if this is standard C++ and why it doesn't compile with Visual Studio, but does with G++?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

橘亓 2024-12-19 14:50:53

它是标准的C++。条件表达式中的 then/else 表达式中的一个(或两个)允许改为 throw 表达式 (C++98 5.16/2)。

如果 Visual Studio 在编译时崩溃...那似乎很不幸!

It is standard C++. Either (or both) of the then/else expressions in a conditional expression is allowed to be a throw-expression instead (C++98 5.16/2).

If Visual Studio crashes when compiling it... that would seem to be unfortunate!

带刺的爱情 2024-12-19 14:50:53

Comeau 编译它没有错误(这是我的最小可编译测试用例):

int main(void)
{
    int x = 17;
    return x ? throw "Something wrong happened" : 5;
}

这是标准允许的很好的证据。事实上,MSVC 崩溃了,而不是因错误而彻底失败。

中得到了修复

R:\>cl ternarythrowtest.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

ternarythrowtest.cpp
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:ternarythrowtest.exe
ternarythrowtest.obj

此外,它似乎在 VC++ 2010和 x64 版本

R:\>cl ternarythrowtest.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

ternarythrowtest.cpp
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:ternarythrowtest.exe
ternarythrowtest.obj

:如果可能,请升级您的编译器,这远不是 2010 年修复的唯一错误。

Comeau compiles it without errors (here's my minimal compilable test case):

int main(void)
{
    int x = 17;
    return x ? throw "Something wrong happened" : 5;
}

which is pretty good evidence that it's allowed by the standard. So is the fact that MSVC crashes, rather than failing cleanly with an error.

Also, it appears to be fixed in VC++ 2010

R:\>cl ternarythrowtest.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

ternarythrowtest.cpp
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:ternarythrowtest.exe
ternarythrowtest.obj

and x64 version:

R:\>cl ternarythrowtest.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

ternarythrowtest.cpp
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:ternarythrowtest.exe
ternarythrowtest.obj

Upgrade your compiler if possible, this is far from the only bug fixed in 2010.

音盲 2024-12-19 14:50:53

来自 C++11 二月草案

§ 5.16/2 如果第二个或第三个操作数的类型为 void(可能是 cv 限定的),则左值到右值 (4.1)、数组到指针 (4.2) 和函数到 -对第二个和第三个操作数执行指针 (4.3) 标准转换,并且应满足以下条件之一:
— 第二个或第三个操作数(但不是两者)是一个 throw 表达式 (15.1);结果是另一个的类型,并且是纯右值。
— 第二个和第三个操作数的类型均为 void;结果是 void 类型并且是纯右值。 [ 注意:这包括两个操作数都是 throw 表达式的情况。 ——尾注]

看来 throw 算作计算为 void,并且这是允许的。

From the C++11 February Draft

§ 5.16/2 If either the second or the third operand has type (possibly cv-qualified) void, then the lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the second and third operands, and one of the following shall hold:
— The second or the third operand (but not both) is a throw-expression (15.1); the result is of the type of the other and is a prvalue.
— Both the second and the third operands have type void; the result is of type void and is a prvalue. [ Note: This includes the case where both operands are throw-expressions. —end note ]

It appears that throw counts as evaluating to a void, and that this is allowed.

荒芜了季节 2024-12-19 14:50:53

内部崩溃可以被视为 Visual Studio 的错误。编译器永远不应该因为正在编译的代码而崩溃。

这是三元运算符的一种非常奇怪的用法,在返回之前使用一个简单的 if 是一个更好的习惯用法:

if(m_something == 0)
    throw std::logic_error("Something wrong happened");

return m_something;

The internal crash can be considered a bug of Visual Studio. A compiler should never crash because of the code being compiled.

This is a very strange usage of the ternary operator, a simple if before the return would be a much preferable idiom:

if(m_something == 0)
    throw std::logic_error("Something wrong happened");

return m_something;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文