質問

私は、これを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でバーフされました。したがって、 throw 式のタイプは無効ではないようです。

では何ですか?

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


これは、条件式演算子がスロー式を処理する方法ほどスロー式のタイプに関するものではないことが判明しました-私は確かにそうしませんでした 今日の前に知っています。回答してくれたすべての人、特にデビッド・ソーンリーに感謝します。

役に立ちましたか?

解決

標準に従って、5.16段落2の最初のポイント"第2または第3オペランド(両方ではない)はthrow-expression(15.1)です。結果は他の型であり、右辺値です。"したがって、条件演算子はthrow-expressionのタイプを気にしませんが、他のタイプを使用します。

実際、15.1段落1には、「A throw-expression is type of void。」と明示的に記載されています

他のヒント

  

" throw-expressionの型はvoid"

ISO14882セクション15

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

  

2番目または3番目のオペランドのいずれかがvoid型の場合(おそらくcv-qualifi ed)voidの場合、左辺値から右辺値、   配列からポインターへの変換、および関数からポインターへの標準変換は、2番目と   第3オペランド、および次のいずれかが保持されます。

     

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

     

— 2番目と3番目のオペランドは両方ともvoid型です。     結果はvoid型であり、右辺値です。     [注:これには、両方のオペランドがthrow-expressionである場合が含まれます。 —終了ノート]

したがって、最初のケースでは // 1 で、 // 2 では、「次のいずれかが成り立つ」ことに違反していました。その場合、そうします。

活字プリンターそれを吐き出すことができます

template<typename T>
struct PrintType;

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

基本的に、 PrintType の実装がないと、コンパイルエラーレポートで次のように表示されます:

  

未定義のテンプレートの暗黙的なインスタンス化 PrintType&lt; void&gt;

したがって、実際に throw 式が void 型であることを確認できます(そして、はい、他の回答に記載されている標準引用符は、これが実装固有の結果ではないことを確認します-gccは貴重な情報を印刷するのに苦労していますが)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top