2009-07-31 2 views
113

私はのredditに私の簡単な進出の一つでこれを拾った:C++では、throwが式の場合、その型は何ですか?

throw "error" 

式です:

http://www.smallshire.org.uk/sufficientlysmall/2009/07/31/in-c-throw-is-an-expression/

基本的に、著者はC++であることを指摘しています。これは、実際には、C++標準では、本文と文法の両方でかなり明確に綴られています。しかし、少なくとも私には明らかでないことは、表現のタイプは何ですか?私は「void」を推測しますが、G ++ 4.4.0とコモで実験のビットは、このコードをもたらした:

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にbarfed条件付き演算子は異なります。したがって、式throwのタイプは無効ではないようです。

だから何ですか?

回答があった場合は、標準からの引用文をバックアップしてください。


これはスロー表現とどのように条件演算子のお得な情報などthrow式のタイプについてはあまりでないことが判明 - 私は確かに が今日前に約知らなかった何か。回答したすべての人に感謝しますが、特にDavid Thornleyに感謝します。

+10

+1恐ろしい質問。そしてそれをテストする巧妙な方法。 –

+1

このリンクは、型がコンパイラによって必要とされるものであると判断されることをかなり明確にしているようです。 – Draemon

+0

リンクされた記事は、私がそれを見てから更新されていると思いますが、実際はそうであると確信しています。しかし、私は標準でそれを見つけることができません。 –

答えて

94

標準、5.16段落2第一点、「第二又は第三のオペランド(に従って、ただし両方ともではない)はthrow式(15.1)であり、結果はもう一方のタイプのものであり、rvalueです。したがって、条件演算子はthrow式がどのタイプのものであるか気にしませんが、他のタイプを使用します。

実際、15.1のパラグラフ1では明示的に「スロー式はvoid型です。 [expr.cond.2](条件演算子?:)から

+9

OK - 勝者がいると思います。 –

+0

throw-expressionは代入式です。したがって、ほとんどの演算子の引数としての構文エラーです。明らかに、それらを括弧で隠すことはできますが、無視されなければ(例えば組み込み演算子の最初の引数)、型エラーです。 – AProgrammer

+4

私は本当に驚きましたが、彼らはこの事件について考えて、合理的なことを起こしました。 – Omnifarious

31

"スロー式はvoid型である"

ISO14882部15

+0

そして、g ++とComeauの両方とも、私の// 1のケースでエラーを出さないことを諦めていますか? –

+2

@Neil、C++/5.16/2によれば、条件演算子の第2オペランドと第3オペランドは 'void 'タイプになる可能性があります。 – mloskot

13

第二又は第三のオペランドのいずれかが、その後左辺ツー右辺値、タイプ(おそらくCV-クアリのfi ED)空隙を有する場合、 へのポインタアレイ、及び機能・ツー・ポインタの標準変換が第 第三のオペランドに対して実行され、次のいずれかが成立しなければならない:

- 第二又は第三のオペランド(両方ではない)でありますスロー式。 結果はもう一方の型の値であり、rvalueです。

- 第2オペランドと第3オペランドの両方にvoid型があります。 結果はvoid型であり、rvalueです。 [注意:これには、両方のオペランドがスロー式である場合も含まれます。 - エンドノートは]

ので、//1とあなたはそれらのどれも行いませんので、その場合には、「保有していなければならない、次のいずれかの」違反して、//2で、最初のケースにありました。

template<typename T> 
struct PrintType; 

int main() 
{ 
    PrintType<decltype(throw "error")> a; 
} 

は、基本的にPrintTypeの実装の欠如は、コンパイルエラーレポートが言うようになります:

3

あなたはタイプのプリンタspit it out for you持つことができ、未定義のテンプレートの

暗黙のインスタンス生成をPrintType<void>

実際に確認できるのはです10式のタイプはvoidです(他の回答に記載されている標準的な引用符は実装固有の結果ではないことを確認していますが、gccは貴重な情報を表示するのに苦労します)

関連する問題