我在一次短暂访问 reddit 时发现了这一点:
http://www.smallshire.org.uk/sufficientlysmall/2009/07/31/in-c-throw-is-an-expression/
基本上,作者指出在 C++ 中:
throw "error"
是一个表达式。 实际上,C++ 标准在正文和语法中都相当清楚地阐明了这一点。 然而,不清楚(至少对我来说)的是表达式的类型是什么? 我猜是“void
”,但是对 g++ 4.4.0 和 Comeau 进行了一些实验,得到了以下代码:
void f() {
}
struct S {};
int main() {
int x = 1;
const char * p1 = x == 1 ? "foo" : throw S(); // 1
const char * p2 = x == 1 ? "foo" : f(); // 2
}
编译器对 //1 没有问题,但对 //2 却感到厌烦,因为 //2 中的类型条件运算符不同。 所以 throw
表达式的类型似乎不是 void。
那么它是什么?
如果您回答,请引用该标准来支持您的陈述。
事实证明,这与抛出表达式的类型无关,而与条件运算符如何处理抛出表达式有关 - 我当然不知道
今天之前就知道了。 感谢所有回复的人,特别是大卫·索恩利。
I picked this up in one of my brief forays to reddit:
http://www.smallshire.org.uk/sufficientlysmall/2009/07/31/in-c-throw-is-an-expression/
Basically, the author points out that in C++:
throw "error"
is an expression. This is actually fairly clearly spelt out in the C++ Standard, both in the main text and the grammar. However, what is not clear (to me at least) is what is the type of the expression? I guessed "void
", but a bit of experimenting with g++ 4.4.0 and Comeau yielded this code:
void f() {
}
struct S {};
int main() {
int x = 1;
const char * p1 = x == 1 ? "foo" : throw S(); // 1
const char * p2 = x == 1 ? "foo" : f(); // 2
}
The compilers had no problem with //1 but barfed on //2 because the the types in the conditional operator are different. So the type of a throw
expression does not seem to be void.
So what is it?
If you answer, please back up your statements with quotes from the Standard.
This turned out not to be so much about the type of a throw expression as how the conditional operator deals with throw expressions - something I certainly didn't
know about before today. Thanks to all who replied, but particularly to David Thornley.
发布评论
评论(4)
根据标准,5.16第2段第一点,“第二个或第三个操作数(但不是两者)是一个抛出表达式(15.1);结果是另一个的类型,并且是一个右值。” 因此,条件运算符并不关心 throw 表达式是什么类型,而只会使用其他类型。
事实上,15.1 第 1 段明确指出“抛出表达式的类型为 void”。
According to the standard, 5.16 paragraph 2 first point, "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 an rvalue." Therefore, the conditional operator doesn't care what type a throw-expression is, but will just use the other type.
In fact, 15.1, paragraph 1 says explicitly "A throw-expression is of type void."
ISO14882 第 15 节
ISO14882 Section 15
来自 [expr.cond.2](条件运算符
?:
):因此,使用
//1
你处于第一种情况,使用//2
,你违反了“以下其中一个应成立”,因为没有在这种情况下,他们中的一些人会这样做。From [expr.cond.2] (conditional operator
?:
):So, with
//1
you were in the first case, with//2
, you were violating "one of the following shall hold", since none of them do, in that case.您可以使用打字打印机 为您吐出内容 :
基本上缺乏 < code>PrintType 将导致编译错误报告显示:
因此我们实际上可以验证
throw
表达式的类型为void
(是的,提到的标准引号在其他答案中验证这不是特定于实现的结果 - 尽管 gcc 很难打印有价值的信息)You can have a type printer spit it out for you :
Basically the lack of implementation for
PrintType
will cause the compilation error report to say :so we can actually verify that
throw
expressions are of typevoid
(and yes, the Standard quotes mentioned in other answers verify that this isn't an implementation specific outcome - though gcc has a hard time printing valuable info)