在C ++中,如果throw是一个表达式,它的类型是什么?

时间:2009-07-31 14:50:00

标签: c++ throw

我在我的一次短暂尝试中选择了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。

4 个答案:

答案 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有很难打印有价值的信息)