例えば、ファイルに含まれる数の合計を計算する場合。
int DoSum(const std::string& file);
ファイルに含まれるのが正の値だけであれば、負の値でエラーを示すことができるが、正も負も含まれる場合には適用できない。
3つのやり方
1. 戻り値はエラーにして、合計は引数で指定された領域に格納
int DoSum(const std::string &file, int &sum) { /* return value of zero indicates a sum has been computed other values indicate an error status */ }
2. エラーと合計を含むデータ構造を定義して戻り値とする
struct ReturnData { int sum; int error_indicator; }; struct ReturnData DoSum(const std::string &file) { }
3. 戻り値は合計で、エラーは例外で扱う
int DoSum(const std::string &file) { /* do calculations */ if (error_has_occurred) throw some_appropriate_exception(); else return calculated_sum; }
1と2の場合、エラーが致命的でなければ呼び出し側で何もする必要がない一方で、エラー処理をしなくても動くので変な結果で処理が進んでしまうことがある。 3の場合、例外をcatchしなくても処理が異常終了するので変な結果が処理が進むことはないのに対し、この関数を使う全ての呼び出し側でcatchして適切に扱うようにしないといけない。
Googleのコード規模でということなので、自分たちのサイズで考える必要がありますが、既存のコードに対して、例外を導入するコストが高いので、 Google C++ Style Guideでは例外は使わないとしています。 ただ、自分たちの問題で考えてみても、関係する全てのコードで新しく例外処理を実装するのはやはり大変なので、1か2を使うことが多い印象です。