1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
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: */
|