我在我的一次短暂尝试中选择了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上进行了禁止,因为条件运算符中的类型不同。所以throw
表达式的类型似乎不是空的。
那是什么?
如果您回答,请使用标准中的引号备份您的陈述。
事实证明,抛出表达式的类型并不像条件运算符处理throw表达式那样 - 我当然没有 在今天之前了解。感谢所有回复的人,特别是David Thornley。
答案 0 :(得分:94)
根据标准,5.16第2段第一点,“第二或第三操作数(但不是两者)是一个throw-expression(15.1);结果是另一个的类型,是一个rvalue。”因此,条件运算符不关心throw-expression是什么类型,而只会使用另一种类型。
事实上,15.1,第1段明确地说“抛出表达式是无效的。”
答案 1 :(得分:31)
“throw-expression的类型为void”
ISO14882第15节
答案 2 :(得分:13)
来自[expr.cond.2](条件运算符?:
):
如果第二个或第三个操作数的类型(可能是cv-quali fi ed)为void,那么左值到右值, 数组到指针,以及函数到指针的标准转换是在第二个和 第三个操作数,以下之一应该成立:
- 第二个或第三个操作数(但不是两个)是一个throw-expression; 结果是另一个的类型,是一个右值。
- 第二个和第三个操作数都有类型void; 结果是void类型,是一个rvalue。 [注意:这包括两个操作数都是throw-expressions的情况。 - 结束说明]
所以,//1
你处于第一种情况,//2
,你违反了“以下其中一项”,因为在这种情况下,他们都没有。
答案 3 :(得分:3)
您可以使用打印机spit it out for you:
template<typename T>
struct PrintType;
int main()
{
PrintType<decltype(throw "error")> a;
}
基本上,PrintType
缺少实现会导致编译错误报告说:
未定义模板
PrintType<void>
的隐式实例化
因此我们实际上可以验证throw
表达式的类型为void
(是的,其他答案中提到的标准引号验证了这不是特定于实现的结果 - 尽管gcc有很难打印有价值的信息)