/// /// @file eo_concrete.hh /// #ifndef EFL_CXX_EO_CONCRETE_HH #define EFL_CXX_EO_CONCRETE_HH #include #include #include #include #include "eo_ops.hh" #ifndef EFL_CXX_THROW #if defined ( EFL_CXX_NO_EXCEPTIONS ) # define EFL_CXX_THROW(x) std::abort() #else # define EFL_CXX_THROW(x) throw (x) #endif #endif #if !defined(EFL_DOXYGEN) && !defined(EO_CXX_INHERIT) # define EO_CXX_INHERIT(name) ::eo_cxx name #elif !defined(EO_CXX_INHERIT) # define EO_CXX_INHERIT(name) name #endif namespace efl { namespace eo { /// @addtogroup Efl_Cxx_API /// @{ /// @brief Creates concrete versions for Eo wrappers. /// /// This class creates the concrete version of all C++ Eo wrappers. /// It holds the Eo pointer that is used on all operations and provides some /// functions for manipulating it. /// struct concrete { /// @brief Class constructor. /// /// @param eo The EO Object. /// /// efl::eo::concrete constructors semantics are that of stealing the /// EO Object lifecycle management. Its constructors do not /// increment the EO reference counter but the destructors /// do decrement. /// explicit concrete(Eo* eo) : _eo_raw(eo) { } /// @brief Default constructor. /// /// Constructs a NULL initialized efl::eo::concrete object. /// concrete() : _eo_raw(nullptr) { } /// @brief Class destructor. /// ~concrete() { if(_eo_raw) detail::unref(_eo_raw); } concrete(concrete const& other) { if(other._eo_raw) _eo_raw = detail::ref(other._eo_raw); } concrete(concrete&& other) { if(_eo_raw) detail::unref(_eo_raw); _eo_raw = other._eo_raw; other._eo_raw = nullptr; } /// @brief Assignment operator. /// concrete& operator=(concrete const& other) { if(_eo_raw) { detail::unref(_eo_raw); _eo_raw = nullptr; } if(other._eo_raw) _eo_raw = detail::ref(other._eo_raw); return *this; } concrete& operator=(concrete&& other) { if(_eo_raw) { detail::unref(_eo_raw); _eo_raw = nullptr; } std::swap(_eo_raw, other._eo_raw); return *this; } /// @brief Return a pointer to the EO Object stored in this /// instance. /// /// @return A pointer to the opaque EO Object. /// Eo* _eo_ptr() const { return _eo_raw; } /// @brief Releases the reference from this concrete object and /// return the pointer to the EO Object stored in this /// instance. /// /// @return A pointer to the opaque EO Object. /// Eo* _release() { Eo* tmp = _eo_raw; _eo_raw = nullptr; return tmp; } /// @brief Reset the current pointer to reference a new Eo object. /// void _reset(Eo* _ptr = nullptr) { if(_eo_raw) detail::unref(_eo_raw); _eo_raw = _ptr; } explicit operator bool() const { return _eo_raw; } protected: Eo* _eo_raw; ///< The opaque EO Object. }; template inline std::basic_ostream& operator<<(std::basic_ostream& os, concrete const& eo) { return os << eo._eo_ptr(); } inline bool operator==(concrete const& lhs, concrete const& rhs) { return lhs._eo_ptr() == rhs._eo_ptr(); } inline bool operator!=(concrete const& lhs, concrete const& rhs) { return !(lhs == rhs); } namespace detail { template struct extension_inheritance; template<> struct extension_inheritance { template struct type { operator concrete() const { return concrete(eo_ref(static_cast(this)->_eo_ptr())); } }; }; } /// @brief Downcast @p U to @p T. /// /// @param T An EO C++ Class. /// @param U An EO C++ Class. /// /// @param object The target object. /// @return This function returns a new instance of @p T if the /// downcast is successful --- otherwise it raises a @c /// std::runtime_error. /// template T downcast(U object) { Eo *eo = object._eo_ptr(); if(detail::isa(eo, T::_eo_class())) { return T(detail::ref(eo)); } else { EFL_CXX_THROW(std::runtime_error("Invalid cast")); } } template struct is_eolian_object : std::false_type {}; template struct is_eolian_object : is_eolian_object {}; template <> struct is_eolian_object : std::true_type {}; /// @} } } // namespace efl { namespace eo { #endif // EFL_CXX_EO_CONCRETE_HH