diff options
author | Noel Grandin <noel@peralex.com> | 2015-01-05 14:01:17 +0200 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2015-04-09 19:55:09 +0100 |
commit | d904316d3da61fdaedf68ebfb6d75abda49600f1 (patch) | |
tree | 8f25db89123dfe5854b8404b16796bff3e49e021 /include | |
parent | 61f1033e4016c1ea77640c123be73612d19a6811 (diff) |
vcl: implement upcasting of VclReference types
to make code less verbose
Change-Id: I0e28bfc412d50e798e6c215434cffc2183b104a6
Diffstat (limited to 'include')
-rw-r--r-- | include/vcl/vclref.hxx | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/include/vcl/vclref.hxx b/include/vcl/vclref.hxx index ba3fdaa70719..b8c15eaea804 100644 --- a/include/vcl/vclref.hxx +++ b/include/vcl/vclref.hxx @@ -22,6 +22,52 @@ #include <rtl/ref.hxx> +/// @cond INTERNAL +namespace vcl { namespace detail { + +// A mechanism to enable up-casts, used by the VclReference conversion constructor, +// heavily borrowed from boost::is_base_and_derived +// (which manages to avoid compilation problems with ambiguous bases and cites +// comp.lang.c++.moderated mail <http://groups.google.com/groups? +// selm=df893da6.0301280859.522081f7%40posting.google.com> "SuperSubclass +// (is_base_and_derived) complete implementation!" by Rani Sharoni and cites +// Aleksey Gurtovoy for the workaround for MSVC), to avoid including Boost +// headers in URE headers (could ultimately be based on C++11 std::is_base_of): + +template< typename T1, typename T2 > struct UpCast { +private: + template< bool, typename U1, typename > struct C + { typedef U1 t; }; + + template< typename U1, typename U2 > struct C< false, U1, U2 > + { typedef U2 t; }; + + struct S { char c[2]; }; + +#if defined _MSC_VER + static char f(T2 *, long); + static S f(T1 * const &, int); +#else + template< typename U > static char f(T2 *, U); + static S f(T1 *, int); +#endif + + struct H { + H(); // avoid C2514 "class has no constructors" from MSVC 2008 +#if defined _MSC_VER + operator T1 * const & () const; +#else + operator T1 * () const; +#endif + operator T2 * (); + }; + +public: + typedef typename C< sizeof (f(H(), 0)) == 1, void *, void >::t t; +}; + +}; }; // namespace detail, namespace vcl + /** * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses. * @param reference_type must be a subclass of vcl::Window @@ -53,6 +99,21 @@ public: : m_rInnerRef (handle.m_rInnerRef) {} + /** Up-casting conversion constructor: Copies interface reference. + + Does not work for up-casts to ambiguous bases. For the special case of + up-casting to Reference< XInterface >, see the corresponding conversion + operator. + + @param rRef another reference + */ + template< class derived_type > + inline VclReference( + const VclReference< derived_type > & rRef, + typename ::vcl::detail::UpCast< reference_type, derived_type >::t = 0 ) + : m_rInnerRef( static_cast<reference_type*>(rRef.get()) ) + { + } /** Get the body. Can be used instead of operator->(). I.e. handle->someBodyOp() and handle.get()->someBodyOp() |