#define BOOST_NO_RVALUE_REFERENCES #include <boost/type_traits/remove_reference.hpp> #include <boost/mpl/if.hpp> #include <boost/none.hpp>
namespace boost_util {
// タイプが参照型ならtrueを返すMPL template <typename T> struct is_reference { static const bool value_type = false; }; template <typename T> struct is_reference<T&> { static const bool value_type = true; };
// boost optionalもどき用。リファレンス型時の型定義 // 保存はポインタ型 template <typename RefT> struct optional_ref { typedef typename boost::remove_reference<RefT>::type NoRefT; typedef RefT ref_t; typedef NoRefT const& cref_t; typedef NoRefT* ptr_t; typedef NoRefT const* cptr_t; typedef ptr_t value_t; // valueはポインタ static ptr_t initializer(ref_t val) { return &val; } // value_t型でvalueを得る。コンストラクタの初期化用 static ptr_t get_value_ptr(value_t val) { return val; } // valueのポインタを得る static cref_t get_value_cref(cptr_t val) { return *val; } static value_t get_invalid_value() { return 0; } // 無効時の値 }; // boost optionalもどき用。通常時の型定義 // 保存は実体 template <typename NoRefT> struct optional_noref { typedef NoRefT& ref_t; typedef NoRefT const& cref_t; typedef NoRefT* ptr_t; typedef NoRefT const* cptr_t; typedef NoRefT value_t; // valueは実体 static cref_t initializer(cref_t val) { return val; } // value_t型でvalueを得る。コンストラクタの初期化用 static ptr_t get_value_ptr(value_t& val) { return &val; } // valueのポインタを得る static cref_t get_value_cref(cref_t& val) { return val; } // valueのconst 参照を得る static value_t get_invalid_value() { return NoRefT(); } // 無効時の値 };
// boost optionalもどき。実装クラス template <typename OptTypeDef> struct optional_impl { typedef typename OptTypeDef::ref_t ref_t; typedef typename OptTypeDef::cref_t cref_t; typedef typename OptTypeDef::ptr_t ptr_t; typedef typename OptTypeDef::cptr_t cptr_t; typedef typename OptTypeDef::value_t value_t; value_t value_; // 保持する値 bool valid_; optional_impl(ref_t val) : value_(OptTypeDef::initializer(val)), valid_(true) {} optional_impl(boost::none_t) : value_(OptTypeDef::get_invalid_value()), valid_(false) {} operator bool () const { return valid_; } ptr_t get_ptr() { return OptTypeDef::get_value_ptr(value_); } cptr_t get_ptr() const { return OptTypeDef::get_value_ptr(value_); } ref_t get() { return *OptTypeDef::get_value_ptr(value_); } cref_t get() const { return OptTypeDef::get_value_cref(value_); } };
// boost optionalもどき。 template <typename UT> struct optional { // UTが参照型か否かでクラスを切り分ける typedef typename boost::mpl::if_c< is_reference<UT>::value_type , optional_ref<UT> , optional_noref<UT> >::type type; typedef typename type::ptr_t ptr_t; typedef typename type::cptr_t cptr_t; typedef typename type::ref_t ref_t; typedef typename type::cref_t cref_t; // 実装はoptional_implに委譲 optional_impl<type> impl_; // コンストラクタ optional(UT val) : impl_(val) {} // コンストラクタ(nil) optional(boost::none_t n = 0) : impl_(n) {} // 実装 operator bool() const { return impl_; } ptr_t operator -> () { return impl_.get_ptr(); } ptr_t get_ptr() { return impl_.get_ptr(); } ref_t get() { return impl_.get(); } ref_t operator * () { return impl_.get(); } cptr_t operator -> () const { return impl_.get_ptr(); } cptr_t get_ptr() const { return impl_.get_ptr(); } cref_t get() const { return impl_.get(); } cref_t operator * () const { return impl_.get(); } cref_t get_value_or(cref_t def) const { if (impl_) return get(); else return def; }
};
}