116

私はこれを reddit への私の短い進出の 1 つで拾いました:

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 にバーフィードしました。したがって、式の型はthrowvoid ではないようです。

それで、それは何ですか?

回答する場合は、基準からの引用を使用してステートメントをバックアップしてください。


これは、throw 式の型ではなく、条件演算子が throw 式をどのように処理するかということであることが判明しました。これについては、今日までまったく知りませんでした。返信してくれたすべての人、特に David Thornley に感謝します。

4

4 に答える 4

96

標準によると、5.16 パラグラフ 2 の最初のポイントは、「2 番目または 3 番目のオペランド (両方ではない) はスロー式 (15.1) です。結果は他方の型であり、右辺値です。」したがって、条件演算子は throw 式の型を気にせず、他の型を使用します。

実際、15.1 のパラグラフ 1 は、「スロー式は void 型です」と明示的に述べています。

于 2009-07-31T15:04:09.187 に答える
32

「スロー式は void 型です」

ISO14882 セクション 15

于 2009-07-31T15:03:19.903 に答える
13

[expr.cond.2](条件付き演算子?:)から:

2番目または3番目のオペランドのいずれかがタイプ(おそらくcv修飾)voidである場合、左辺値から右辺値、配列からポインター、および関数からポインターの標準変換が2番目と3番目のオペランドで実行されます。次のいずれかが成立します。

— 2番目または3番目のオペランド(両方ではない)はthrow-expressionです。結果は他のタイプであり、右辺値です。

—2番目と3番目のオペランドはどちらもvoid型です。結果はvoid型であり、右辺値です。[注:これには、両方のオペランドがスロー式である場合が含まれます。—エンドノート]

したがって、//1最初のケースでは、で//2、「次のいずれかが成立する」に違反していました。その場合、いずれも違反していません。

于 2009-07-31T15:07:52.160 に答える
3

タイププリンターに吐き出させることができます

template<typename T>
struct PrintType;

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

基本的に、 の実装が不足しているPrintTypeと、コンパイル エラー レポートに次のように表示されます。

未定義のテンプレートの暗黙的なインスタンス化PrintType<void>

throwそのため、式がタイプであることを実際に確認できvoidます(はい、他の回答で言及されている標準の引用符は、これが実装固有の結果ではないことを確認します-gccは貴重な情報を出力するのに苦労しています)

于 2015-07-03T10:42:27.213 に答える