質問
私は、これを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は貴重な情報を印刷するのに苦労していますが)