blob: 99599b78ba19c38c81f86d2231e98a2b39caf7fd [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#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 explicitely
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