- 追加された行はこの色です。
- 削除された行はこの色です。
[[MPLtop]]
#define BOOST_NO_RVALUE_REFERENCES
#include <boost/type_traits/remove_reference.hpp>
#include <boost/mpl/if.hpp>
#include <boost/none.hpp>
#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 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; }
};
}