これをクラステンプレート化した。
インタフェース:
namespace shand { template <class ValueType, class Enum> class special_value { public: using value_type = ValueType; using enum_type = Enum; special_value(); // initialize ValueType special_value(ValueType value); special_value(Enum e); special_value& operator=(ValueType value); special_value& operator=(Enum e); // どちらの値が入っているかの判定 bool has_value() const; bool has_enum() const; // 値の取り出し // それぞれの型の値が入っていない場合は、boost::bad_get例外を送出する ValueType& get_value(); const ValueType& get_value() const; Enum& get_enum(); const Enum& get_enum() const; // それぞれの型の値が入っていたときに指定された関数オブジェクトを呼び出す。 // 入っていなかったら関数オブジェクトを呼び出さない。 // *thisを返す。 template <class F> // void(ValueType& value) or void(ValueType& value) special_value& on_value(F f); template <class F> const special_value& on_value(F f) const; template <class F> // void(Enum value) or void(Enum& value) special_value& on_enum(F f); template <class F> const special_value& on_enum(F f) const; }; }
例:
#include <iostream> #include <shand/special_value.hpp> enum class PopType { Root }; std::string popToString(PopType) { return "Root"; } int main() { // size_tかPopTypeのどちらかの型の値が入る shand::special_value<std::size_t, PopType> pop_count = 1u; // pop_count = PopType::Root; // size_tの値が入っていたときの処理 pop_count.on_value([](std::size_t value) { std::cout << value << std::endl; }) // PopTypeの値が入っていたときの処理 .on_enum([](PopType pop) { std::cout << popToString(pop) << std::endl; }); }
出力:
1
実装はboost::variant
のラッパー。設計は、expected
を参考にした。クラス名はこれでいいのか、まだ悩み中。もしかしたら変えるかも。