エラー許容型を作った

errorableというクラスを作りました。エラーになった理由を持てるoptionalです。実装は、boost::variantのラッパー。Eitherみたいなものです。

#include <iostream>
#include <system_error>
#include <shand/errorable.hpp>

int main()
{
    // 初期状態はエラー
    {
        shand::errorable<int> x;
        BOOST_ASSERT(x.is_error());
    }

    // エラーが発生しているケース
    // エラー理由を格納する
    // デフォルトのエラー型はstd::string
    {
        shand::errorable<int> value = shand::error("invalid argument");
        if (boost::optional<std::string> err = value.get_error()) {
            std::cout << err.get() << std::endl;
        }
    }

    // 正常な値が入っているケース
    {
        shand::errorable<int> value = 3;
        if (boost::optional<int> x = value.get_value()) {
            std::cout << x.get() << std::endl;
        }
    }

    // 値が正常かエラーかによって、関数を呼び分ける
    {
        shand::errorable<int> value = shand::error("invalid argument");
        value.value_if([](int x) {
            std::cout << x << std::endl;
        })
        .error_if([](const std::string& err) {
            std::cout << err << std::endl;
        });
    }

    // 第2テンプレート引数で、エラー型をカスタマイズ可能
    {
        shand::errorable<int, std::errc> value = shand::error(std::errc::invalid_argument);
        if (boost::optional<std::errc> err = value.get_error()) {
            std::cout << std::make_error_code(err.get()).message() << std::endl;
        }
    }
}
invalid argument
3
invalid argument
Invalid argument

ソースファイル:
https://github.com/faithandbrave/Shand/blob/master/shand/errorable.hpp


現状の機能:

  • 第1テンプレート引数で、正常値の型をとる
  • 第2テンプレート引数で、エラー値の型をとる(デフォルトはstd::string)
  • エラー値は、error()フリー関数を通してerrorableオブジェクトに代入する。
  • get_value()get_error()メンバ関数で、正常値もしくはエラー値を取得できる。返されるのはboost::optional
  • value_if()error_if()メンバ関数で、正常値もしくはエラー値どちらかの場合のみに呼び出される関数を指定できる。


現状の問題:

  • errorableという名前はtypoしやすい。別の名前を検討する。
  • デフォルトコンストラクトした状態は、「デフォルトのエラー値」となってしまって使いにくい。empty状態を用意すべきか。
  • value_if()error_if()の戻り値は、現在はvoidだが、なんとか値を返せないだろうか。