続・boost::optional<ErrorCode>を戻り値にする設計

Twitterでおもしろい方法を教えてもらいました。



ErrorCodeの単純なラッパークラスを作り、boost::optionalへの型変換演算子を用意することで、
boost::optionalへの変換はできるけど、boolへのダイレクトな変換を用意しないことによってif (FileOpen())のような書き方を禁止するという方法です。

#include <iostream>
#include <string>
#include <boost/optional.hpp>

struct ErrorCode {
    enum enum_t {
        FileNotFound
    };
};

std::string to_string(ErrorCode::enum_t error)
{
    switch (error) {
        case ErrorCode::FileNotFound: return "File Not Found";
    }
    assert(false);
}

template <class T>
class error {
    boost::optional<T> value;
public:
    error() {}
    error(T value) : value(value) {}

    operator boost::optional<T>() const
    {
        return value;
    }
};

error<ErrorCode::enum_t> FileOpen()
{
    return ErrorCode::FileNotFound;
}

int main()
{
    if (boost::optional<ErrorCode::enum_t> error = FileOpen()) {
        std::cout << to_string(error.get()) << std::endl;
    }

/*  if (FileOpen()) { // コンパイルエラー!boolに変換できない
        std::cout << "file open error" << std::endl;
    }
*/
}
FileNotFound

これはすばらしいですね。