lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
opaque_val.h
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