summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cppu/qa/test_reference.cxx43
-rw-r--r--include/com/sun/star/uno/Reference.h66
-rw-r--r--include/com/sun/star/uno/Reference.hxx12
-rw-r--r--sd/source/core/CustomAnimationEffect.cxx2
4 files changed, 122 insertions, 1 deletions
diff --git a/cppu/qa/test_reference.cxx b/cppu/qa/test_reference.cxx
index b998238f6b39..a6e393692043 100644
--- a/cppu/qa/test_reference.cxx
+++ b/cppu/qa/test_reference.cxx
@@ -149,4 +149,47 @@ CPPUNIT_TEST_SUITE_REGISTRATION(Test);
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 94551a087063..27787d3ec1ef 100644
--- a/include/com/sun/star/uno/Reference.h
+++ b/include/com/sun/star/uno/Reference.h
@@ -160,6 +160,57 @@ enum UnoReference_SetThrow
};
#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 @@ public:
@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 aa39810159d3..419439ecbb9a 100644
--- a/include/com/sun/star/uno/Reference.hxx
+++ b/include/com/sun/star/uno/Reference.hxx
@@ -122,6 +122,18 @@ inline Reference< interface_type >::Reference( const Reference< interface_type >
_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 21a098f7ee2f..827bed2af29f 100644
--- a/sd/source/core/CustomAnimationEffect.cxx
+++ b/sd/source/core/CustomAnimationEffect.cxx
@@ -1022,7 +1022,7 @@ Reference< XAnimationNode > CustomAnimationEffect::createAfterEffectNode() const
xAnimate->setFill( AnimationFill::HOLD );
xAnimate->setTarget( maTarget );
- return Reference< XAnimationNode >( xAnimate, UNO_QUERY_THROW );
+ return xAnimate;
}
// --------------------------------------------------------------------