summaryrefslogtreecommitdiff
path: root/include/comphelper/implementationreference.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'include/comphelper/implementationreference.hxx')
-rw-r--r--include/comphelper/implementationreference.hxx267
1 files changed, 267 insertions, 0 deletions
diff --git a/include/comphelper/implementationreference.hxx b/include/comphelper/implementationreference.hxx
new file mode 100644
index 000000000000..7957d6437ff5
--- /dev/null
+++ b/include/comphelper/implementationreference.hxx
@@ -0,0 +1,267 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
+#define _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XInterface.hpp>
+
+namespace comphelper
+{
+
+ /** Holds a uno::Reference alongside a C++ implementation pointer
+
+ This template is useful to accomplish the following task: the
+ client needs an implementation pointer to an object providing
+ UNO interfaces. It is unsafe to simply store a C++ pointer,
+ because of the automatic UNO lifetime control. It is
+ inconvenient to always cast the UNO interface to the C++
+ implementation, and what's more, it's mostly unclear to the
+ casual code reader.
+
+ Thus, this template nicely encapsulate the stated intention,
+ by holding a uno::Reference internally, and providing simple
+ C++ pointer semantics to the outside. As a differentiator to
+ ::rtl::Reference, this template features a getRef() method,
+ giving you friction-less access to the internal UNO interface,
+ without extra querying.
+
+ By the way, the pointer semantic of this template include
+ transitive constness. That means, if this template's instance
+ is const (e.g. because it is a member of a class which is
+ accessed in a const method), the pointer returned is also
+ const.
+
+ As this template is geared towards fast, internal pointer
+ access, validity of the UNO reference is _not_ checked for
+ every pointer access. The client of this template is
+ responsible to check that, whereever necessary, via the is()
+ method.
+
+ @tpl CppType
+ The C++ type this class should mimick a pointer to (not the
+ pointer type itself!).
+
+ @tpl UnoType
+ The UNO interface type of the object (a uno::Reference to this
+ type is held internally).
+
+ @tpl XIfType
+ An unambiguous derivative of UnoType. This is defaulted to
+ the second template parameter (UnoType), which should normally
+ just work, since one typically has only single inheritance in
+ UNO.<p>
+ Alternatively, when using the
+ ImplementationReference::createFromQuery() method to create an
+ instance, this type can serve a different need: if the
+ provided CppType only derives from XInterface (generally
+ speaking, derives from a UNO interface above UnoType in the
+ class hierarchy), then the default XIfType constitutes a
+ possibly invalid downcast to UnoType. Setting XIfType equal to
+ CppTypes's most derived UNO interface type then solves this
+ problem (which is not as arcane as it seems to be. Just
+ imagine you're providing a C++ abstract interface, which must
+ provide UNO reference semantics. Naturally, you will derive
+ this C++ interface only from XInterface, to reduce the number
+ of ambiguous classes. Even more naturally, it is reasonable to
+ have UnoType be something different from XInterface, governed
+ by the usage of the C++ interface)
+
+ @sample ImplementationReference< MyCppType, XMyInterface >
+
+ @sample ImplementationReference< MyAbstractCppType, XMyInterface, XInterface >
+ for an abstract C++ class
+
+ @see ::rtl::Reference
+
+ */
+ template < class CppType,
+ class UnoType,
+ class XIfType=UnoType > class ImplementationReference
+ {
+ public:
+
+ typedef UnoType UnoInterfaceType;
+ typedef CppType ImplementationType;
+ typedef XIfType UnambiguousXInterfaceType;
+
+ /** Default-construct an ImplementationReference
+
+ Uno reference will be invalid, implementation pointer will
+ be NULL.
+ */
+ ImplementationReference() :
+ mxRef(),
+ mpImpl( NULL )
+ {
+ }
+
+ /** Create an ImplementationReference from C++ pointer.
+
+ This constructor does not perform an explicit
+ QueryInterface on the provided implementation object, but
+ constructs the UNO reference directly from the given
+ pointer. This is the fastest, and most often the best way
+ to create an ImplementationReference. If the conversion
+ between the implementation object and the required UNO
+ interface is ambiguous, provide the third template
+ parameter with a type that can be unambiguously upcasted
+ to the UNO interface (the second template parameter).
+
+ There are cases, however, where performing a
+ QueryInterface is the better, albeit slower choice. In
+ these cases, createFromQuery() should be used.
+
+ @param pImpl
+ Pointer to the C++ implementation type
+
+ @see createFromQuery()
+ */
+ explicit ImplementationReference( ImplementationType* pImpl ) :
+ mxRef( static_cast<UnambiguousXInterfaceType*>(pImpl) ),
+ mpImpl( pImpl )
+ {
+ }
+
+ struct CreateFromQuery { };
+ /** Create an ImplementationReference from C++ pointer
+
+ @param pImpl
+ The pointer to the C++ implementation type, which is
+ queried for the template-parameterized UNO type.
+
+ @param dummy
+ Dummy parameter, to distinguish this contructor from the
+ default unary one (which does not perform a
+ QueryInterface)
+ */
+ ImplementationReference( ImplementationType* pImpl, CreateFromQuery ) :
+ mxRef( static_cast<UnambiguousXInterfaceType*>(pImpl),
+ ::com::sun::star::uno::UNO_QUERY ),
+ mpImpl( pImpl )
+ {
+ }
+
+ /** Factory method to create an ImplementationReference from
+ C++ pointer.
+
+ This is a static version of the constructor which creates
+ an instance of an implementation type which is explicitly
+ queried for the ImplementationReference's
+ template-parameterized UNO type.
+
+ @sample
+ mpRef = mpRef.createFromQuery( new ImplementationType );
+ */
+ static ImplementationReference createFromQuery( ImplementationType* pImpl )
+ {
+ return ImplementationReference( pImpl, CreateFromQuery() );
+ }
+
+ /** Query whether the pointer is still valid.
+
+ Hands off also from the implementation pointer if this
+ returns false!
+ */
+ bool is() const { return mxRef.is(); }
+
+ /** Get a pointer to the implementation object
+
+ Compatibility method to get an auto_ptr-compatible
+ interface
+ */
+ ImplementationType* get() { return mpImpl; }
+ const ImplementationType* get() const { return mpImpl; }
+
+ /** Release all references
+
+ Compatibility method to get an auto_ptr-compatible
+ interface
+ */
+ void reset() { dispose(); }
+
+ /** Release all references
+
+ This method releases the UNO interface reference, and
+ clears the C++ pointer to NULL.
+ */
+ void dispose() { mxRef = NULL; mpImpl=NULL; }
+
+ ImplementationType* operator->() { return mpImpl; }
+ const ImplementationType* operator->() const { return mpImpl; }
+
+ ImplementationType& operator*() { return *mpImpl; }
+ const ImplementationType& operator*() const { return *mpImpl; }
+
+ /// Access to the underlying UNO reference, without extra querying
+ ::com::sun::star::uno::Reference< UnoInterfaceType > getRef() { return mxRef; }
+
+ /// Access to the underlying UNO reference, without extra querying
+ const ::com::sun::star::uno::Reference< UnoInterfaceType >& getRef() const { return mxRef; }
+
+ // default destructor, copy constructor and assignment will do
+ // ~ImplementationReference();
+ // ImplementationReference( const ImplementationReference& );
+ // ImplementationReference& operator= ( const ImplementationReference& );
+
+ /** Comparison operator
+
+ Object identity is defined to be identity of the
+ implementation pointers. This is in general invalid when
+ comparing pointers to UNO objects (ambiguous class
+ hierarchies, optimizations in the bridges, etc.), but okay
+ for raw C++ pointers (which is what's compared herein).
+ */
+ bool operator==( const ImplementationReference& rhs ) const
+ {
+ return mpImpl == rhs.mpImpl;
+ }
+
+ /** less-than operator
+
+ Object order is defined to be the ordering of the
+ implementation pointers. This is in general invalid when
+ comparing pointers to UNO objects (ambiguous class
+ hierarchies, optimizations in the bridges, etc.), but okay
+ for raw C++ pointers (which is what's used herein).
+
+ This ordering complies with STL's strict weak ordering
+ concept.
+ */
+ bool operator<( const ImplementationReference& rhs ) const
+ {
+ return mpImpl < rhs.mpImpl;
+ }
+
+ private:
+
+ // the interface, hard reference to prevent object from vanishing
+ ::com::sun::star::uno::Reference< UnoInterfaceType > mxRef;
+
+ // the c++ object, for our internal stuff
+ ImplementationType* mpImpl;
+
+ };
+
+}
+
+#endif // _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */