lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
00001 /*****************************************************/ 00002 /* lean PImpl (c) Tobias Zirr 2011 */ 00003 /*****************************************************/ 00004 00005 #ifndef LEAN_PIMPL_OPAQUE_VAL 00006 #define LEAN_PIMPL_OPAQUE_VAL 00007 00008 #include "../cpp0x.h" 00009 #include "../meta/conditional.h" 00010 #include "../meta/dereference.h" 00011 00012 namespace lean 00013 { 00014 namespace pimpl 00015 { 00016 00021 template <class OpaqueTypeWrapper, class OpaqueTypeWrapperBase> 00022 class opaque_val 00023 { 00024 private: 00025 typename OpaqueTypeWrapperBase::type m_value; 00026 00027 public: 00029 typedef typename OpaqueTypeWrapperBase::type opaque_type; 00031 typedef typename complete_type_or_base<OpaqueTypeWrapper, OpaqueTypeWrapperBase>::type::type actual_type; 00033 typedef typename maybe_dereference_once<actual_type>::value_type dereferenced_type; 00035 typedef typename conditional_type< 00036 maybe_dereference_once<actual_type>::dereferenced, 00037 dereferenced_type&, dereferenced_type>::type dereferenced_return_type; 00039 static const bool is_opaque = !complete_type_or_base<OpaqueTypeWrapper, OpaqueTypeWrapperBase>::is_complete; 00040 00042 opaque_val(const actual_type &value = actual_type()) 00043 : m_value(value) 00044 { 00045 LEAN_STATIC_ASSERT_MSG_ALT(!is_opaque, "cannot construct value in opaque state", cannot_construct_value_in_opaque_state); 00046 } 00047 #ifndef LEAN0X_NO_RVALUE_REFERENCES 00048 00049 opaque_val(opaque_val &&right) : m_value(std::move(right.m_value)) { } 00050 #endif 00051 00053 opaque_val& operator =(const actual_type &value) 00054 { 00055 LEAN_STATIC_ASSERT_MSG_ALT(!is_opaque, "cannot assign value in opaque state", cannot_assign_value_in_opaque_state); 00056 00057 m_value = value; 00058 return *this; 00059 } 00060 #ifndef LEAN0X_NO_RVALUE_REFERENCES 00061 00062 opaque_val& operator =(opaque_val &&right) 00063 { 00064 m_value = std::move(right.m_value); 00065 return *this; 00066 } 00067 #endif 00068 00070 actual_type get(void) const { return static_cast<actual_type>(m_value); } 00071 00073 dereferenced_return_type operator *() const { return maybe_dereference_once<actual_type>::dereference(get()); } 00075 actual_type operator ->() const { return get(); } 00076 00078 operator actual_type() const { return get(); } 00079 }; 00080 00081 } // namespace 00082 00083 using pimpl::opaque_val; 00084 00085 } // namespace 00086 00090 00093 #define DECLARE_OPAQUE_TYPE(NAME, OPAQUE_TYPE) \ 00094 struct NAME##_opaque_type_wrapper \ 00095 { \ 00096 typedef OPAQUE_TYPE type; \ 00097 }; \ 00098 \ 00099 struct NAME##_actual_type_wrapper; \ 00100 \ 00101 typedef ::lean::opaque_val< \ 00102 NAME##_actual_type_wrapper, \ 00103 NAME##_opaque_type_wrapper> NAME; 00104 00108 #define DEFINE_OPAQUE_TYPE(NAME, ACTUAL_TYPE) \ 00109 struct NAME##_actual_type_wrapper : public NAME##_opaque_type_wrapper \ 00110 { \ 00111 typedef ACTUAL_TYPE type; \ 00112 }; 00113 00115 00116 #endif