/// /// @file eo_concrete.hh /// #ifndef EFL_CXX_EO_CONCRETE_HH #define EFL_CXX_EO_CONCRETE_HH #include #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 /// @{ struct instantiate_t { #ifdef EFL_CXXPERIMENTAL /// @brief A helper to create objects with a different syntax /// /// @param obj The object to instantiate /// @return obj The newly created object /// /// Consider an object declared by its type T on the stack, like T obj. /// Initially it will be empty (_eo_ptr() is nullptr). It can be created /// in two ways: /// obj = T(instantiate, obj); /// or: /// instantiate(obj); /// /// Note that if @c obj is already a valid object, it will be unreferenced. template T& operator()(T& obj) const { obj = T(*this); return obj; } #endif }; /// @brief The handle to use to create real EFL objects /// /// Use @c instantiate as first argument of any object constructor in order /// to trigger a real EFL object creation. The following syntax is preferred: /// T obj(instantiate, ...); instantiate_t const instantiate = {}; #ifdef EFL_CXXPERIMENTAL instantiate_t const add = {}; #endif /// @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) : _eo_raw(nullptr) { if(other._eo_raw) _eo_raw = detail::ref(other._eo_raw); } concrete(concrete&& other) { _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); else _eo_raw = nullptr; return *this; } concrete& operator=(concrete&& other) { concrete tmp(std::move(other)); swap(tmp); 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; } void _delete() { Eo* tmp = _eo_raw; _eo_raw = nullptr; detail::del(tmp); } explicit operator bool() const { return _eo_raw; } friend void swap(concrete& lhs, concrete& rhs) { lhs.swap(rhs); } void swap(concrete& other) { std::swap(_eo_raw, other._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")); } } /// @} } } // namespace efl { namespace eo { #endif // EFL_CXX_EO_CONCRETE_HH