Date: prev next · Thread: first prev next last
2013 Archives by date, by thread · List index


Hi,

I have submitted a patch for review:

    https://gerrit.libreoffice.org/3699

To pull it, you can do:

    git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/99/3699/1

Up-cast conversion constructor for css::uno::Reference

Based on a previous patch by Noel Grandin,
<https://gerrit.libreoffice.org/#/c/3613/>, and borrowing from
boost::is_base_and_derived (see comment in include/com/sun/star/uno/Reference.h)
to avoid including Boost headers in URE headers.

Change-Id: Iade5af144dd73ef03bd7d96000134c7a66a5e591
---
M cppu/qa/test_reference.cxx
M include/com/sun/star/uno/Reference.h
M include/com/sun/star/uno/Reference.hxx
M sd/source/core/CustomAnimationEffect.cxx
4 files changed, 122 insertions(+), 1 deletion(-)



diff --git a/cppu/qa/test_reference.cxx b/cppu/qa/test_reference.cxx
index b998238..a6e3936 100644
--- a/cppu/qa/test_reference.cxx
+++ b/cppu/qa/test_reference.cxx
@@ -149,4 +149,47 @@
 
 CPPUNIT_PLUGIN_IMPLEMENT();
 
+// Check that the up-casting Reference conversion constructor catches the
+// intended cases:
+
+namespace {
+
+struct Base1: public css::uno::XInterface { virtual ~Base1() {} };
+struct Base2: public Base1 { virtual ~Base2() {} };
+struct Base3: public Base1 { virtual ~Base3() {} };
+struct Derived: public Base2, public Base3 { virtual ~Derived() {} };
+
+}
+
+// The special case using the conversion operator instead:
+css::uno::Reference< css::uno::XInterface > testUpcast1(
+    css::uno::Reference< Derived > const & ref)
+{ return ref; }
+
+// The normal up-cast case:
+css::uno::Reference< Base1 > testUpcast2(
+    css::uno::Reference< Base2 > const & ref)
+{ return ref; }
+
+// Commenting this in should cause a compiler error due to an ambiguous up-cast:
+/*
+css::uno::Reference< Base1 > testFailingUpcast3(
+    css::uno::Reference< Derived > const & ref)
+{ return ref; }
+*/
+
+// Commenting this in should cause a compiler error due to a down-cast:
+/*
+css::uno::Reference< Base2 > testFailingUpcast4(
+    css::uno::Reference< Base1 > const & ref)
+{ return ref; }
+*/
+
+// Commenting this in should cause a compiler error due to a down-cast:
+/*
+css::uno::Reference< Base1 > testFailingUpcast5(
+    css::uno::Reference< css::uno::XInterface > const & ref)
+{ return ref; }
+*/
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/com/sun/star/uno/Reference.h b/include/com/sun/star/uno/Reference.h
index 94551a0..27787d3 100644
--- a/include/com/sun/star/uno/Reference.h
+++ b/include/com/sun/star/uno/Reference.h
@@ -160,6 +160,57 @@
 };
 #endif
 
+/// @cond INTERNAL
+namespace detail {
+
+// A mechanism to enable up-casts, used by the Reference conversion constructor,
+// but at the same time disable up-casts to XInterface, so that the conversion
+// operator for that special case is used in an expression like
+// Reference< XInterface >(x); 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;
+};
+
+template< typename T2 > struct UpCast< XInterface, T2 > {};
+
+}
+/// @endcond
+
 /** Template reference class for interface type derived from BaseReference.
     A special constructor given the UNO_QUERY identifier queries interfaces
     for reference type.
@@ -248,6 +299,21 @@
         @param rRef another reference
     */
     inline Reference( const Reference< interface_type > & rRef ) SAL_THROW(());
+
+    /** 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 Reference(
+        const Reference< derived_type > & rRef,
+        typename detail::UpCast< interface_type, derived_type >::t = 0 )
+        SAL_THROW(());
+
     /** Constructor: Sets given interface pointer.
 
         @param pInterface an interface pointer
diff --git a/include/com/sun/star/uno/Reference.hxx b/include/com/sun/star/uno/Reference.hxx
index aa39810..419439e 100644
--- a/include/com/sun/star/uno/Reference.hxx
+++ b/include/com/sun/star/uno/Reference.hxx
@@ -122,6 +122,18 @@
         _pInterface->acquire();
 }
 
//__________________________________________________________________________________________________
+template< class interface_type > template< class derived_type >
+inline Reference< interface_type >::Reference(
+    const Reference< derived_type > & rRef,
+    typename detail::UpCast< interface_type, derived_type >::t )
+    SAL_THROW(())
+{
+    interface_type * p = rRef.get();
+    _pInterface = p;
+    if (_pInterface)
+        _pInterface->acquire();
+}
+//__________________________________________________________________________________________________
 template< class interface_type >
 inline Reference< interface_type >::Reference( interface_type * pInterface ) SAL_THROW(())
 {
diff --git a/sd/source/core/CustomAnimationEffect.cxx b/sd/source/core/CustomAnimationEffect.cxx
index 21a098f..827bed2 100644
--- a/sd/source/core/CustomAnimationEffect.cxx
+++ b/sd/source/core/CustomAnimationEffect.cxx
@@ -1022,7 +1022,7 @@
     xAnimate->setFill( AnimationFill::HOLD );
     xAnimate->setTarget( maTarget );
 
-    return Reference< XAnimationNode >( xAnimate, UNO_QUERY_THROW );
+    return xAnimate;
 }
 
 // --------------------------------------------------------------------

-- 
To view, visit https://gerrit.libreoffice.org/3699
To unsubscribe, visit https://gerrit.libreoffice.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iade5af144dd73ef03bd7d96000134c7a66a5e591
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: master
Gerrit-Owner: Stephan Bergmann <sbergman@redhat.com>


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.