私はこれを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
式のタイプは無効ではないようです。
それで、それは何ですか?
回答する場合は、標準からの引用でステートメントをバックアップしてください。
これは、条件演算子がスロー式を処理する方法ほど、スロー式のタイプについてではないことが判明しました-今日まで私が確かに知らなかったことです。返信してくれたすべての人に感謝しますが、特にDavid Thornleyに感謝します。
標準の5.16段落2の最初のポイントによると、「2番目または3番目のオペランド(両方ではない)はスロー式(15.1)であり、結果はもう一方の型であり、右辺値です。」したがって、条件演算子は、throw-expressionがどのタイプであるかを気にせず、他のタイプを使用するだけです。
実際、15.1、段落1は、「throw-expressionはvoid型です」と明示的に述べています。
「throw-expressionはvoid型です」
ISO14882セクション15
[expr.cond.2]から(条件演算子?:
):
2番目または3番目のオペランドのいずれかがタイプ(おそらくcv修飾)voidである場合、左辺値から右辺値、配列からポインター、および関数からポインターの標準変換が2番目と3番目のオペランドで実行されます。次のいずれかが成立します。
— 2番目または3番目のオペランド(両方ではない)はスロー式です。結果は他のタイプであり、右辺値です。
—2番目と3番目のオペランドはどちらもvoid型です。結果はvoid型であり、右辺値です。 [注:これには、両方のオペランドがスロー式である場合が含まれます。 —エンドノート]
したがって、//1
あなたは最初のケースで、//2
、あなたは「次のいずれかが成立する」に違反していました。その場合、いずれも違反していません。
あなたはタイププリンターを持つことができます あなたのためにそれを吐き出してください :
template<typename T>
struct PrintType;
int main()
{
PrintType<decltype(throw "error")> a;
}
基本的に、PrintType
の実装がないため、コンパイルエラーレポートに次のように表示されます。
未定義のテンプレートの暗黙的なインスタンス化
PrintType<void>
したがって、throw
式がvoid
型であることを実際に確認できます(もちろん、他の回答で言及されている標準引用符は、これが実装固有の結果ではないことを確認しています-gccは苦労していますが貴重な情報を印刷する)