Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
21 : #define _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
22 :
23 : #include <com/sun/star/uno/Reference.hxx>
24 : #include <com/sun/star/uno/XInterface.hpp>
25 :
26 : namespace comphelper
27 : {
28 :
29 : /** Holds a uno::Reference alongside a C++ implementation pointer
30 :
31 : This template is useful to accomplish the following task: the
32 : client needs an implementation pointer to an object providing
33 : UNO interfaces. It is unsafe to simply store a C++ pointer,
34 : because of the automatic UNO lifetime control. It is
35 : inconvenient to always cast the UNO interface to the C++
36 : implementation, and what's more, it's mostly unclear to the
37 : casual code reader.
38 :
39 : Thus, this template nicely encapsulate the stated intention,
40 : by holding a uno::Reference internally, and providing simple
41 : C++ pointer semantics to the outside. As a differentiator to
42 : ::rtl::Reference, this template features a getRef() method,
43 : giving you friction-less access to the internal UNO interface,
44 : without extra querying.
45 :
46 : By the way, the pointer semantic of this template include
47 : transitive constness. That means, if this template's instance
48 : is const (e.g. because it is a member of a class which is
49 : accessed in a const method), the pointer returned is also
50 : const.
51 :
52 : As this template is geared towards fast, internal pointer
53 : access, validity of the UNO reference is _not_ checked for
54 : every pointer access. The client of this template is
55 : responsible to check that, whereever necessary, via the is()
56 : method.
57 :
58 : @tpl CppType
59 : The C++ type this class should mimick a pointer to (not the
60 : pointer type itself!).
61 :
62 : @tpl UnoType
63 : The UNO interface type of the object (a uno::Reference to this
64 : type is held internally).
65 :
66 : @tpl XIfType
67 : An unambiguous derivative of UnoType. This is defaulted to
68 : the second template parameter (UnoType), which should normally
69 : just work, since one typically has only single inheritance in
70 : UNO.<p>
71 : Alternatively, when using the
72 : ImplementationReference::createFromQuery() method to create an
73 : instance, this type can serve a different need: if the
74 : provided CppType only derives from XInterface (generally
75 : speaking, derives from a UNO interface above UnoType in the
76 : class hierarchy), then the default XIfType constitutes a
77 : possibly invalid downcast to UnoType. Setting XIfType equal to
78 : CppTypes's most derived UNO interface type then solves this
79 : problem (which is not as arcane as it seems to be. Just
80 : imagine you're providing a C++ abstract interface, which must
81 : provide UNO reference semantics. Naturally, you will derive
82 : this C++ interface only from XInterface, to reduce the number
83 : of ambiguous classes. Even more naturally, it is reasonable to
84 : have UnoType be something different from XInterface, governed
85 : by the usage of the C++ interface)
86 :
87 : @sample ImplementationReference< MyCppType, XMyInterface >
88 :
89 : @sample ImplementationReference< MyAbstractCppType, XMyInterface, XInterface >
90 : for an abstract C++ class
91 :
92 : @see ::rtl::Reference
93 :
94 : */
95 : template < class CppType,
96 : class UnoType,
97 944 : class XIfType=UnoType > class ImplementationReference
98 : {
99 : public:
100 :
101 : typedef UnoType UnoInterfaceType;
102 : typedef CppType ImplementationType;
103 : typedef XIfType UnambiguousXInterfaceType;
104 :
105 : /** Default-construct an ImplementationReference
106 :
107 : Uno reference will be invalid, implementation pointer will
108 : be NULL.
109 : */
110 514 : ImplementationReference() :
111 : mxRef(),
112 514 : mpImpl( NULL )
113 : {
114 514 : }
115 :
116 : /** Create an ImplementationReference from C++ pointer.
117 :
118 : This constructor does not perform an explicit
119 : QueryInterface on the provided implementation object, but
120 : constructs the UNO reference directly from the given
121 : pointer. This is the fastest, and most often the best way
122 : to create an ImplementationReference. If the conversion
123 : between the implementation object and the required UNO
124 : interface is ambiguous, provide the third template
125 : parameter with a type that can be unambiguously upcasted
126 : to the UNO interface (the second template parameter).
127 :
128 : There are cases, however, where performing a
129 : QueryInterface is the better, albeit slower choice. In
130 : these cases, createFromQuery() should be used.
131 :
132 : @param pImpl
133 : Pointer to the C++ implementation type
134 :
135 : @see createFromQuery()
136 : */
137 640 : explicit ImplementationReference( ImplementationType* pImpl ) :
138 : mxRef( static_cast<UnambiguousXInterfaceType*>(pImpl) ),
139 640 : mpImpl( pImpl )
140 : {
141 640 : }
142 :
143 : struct CreateFromQuery { };
144 : /** Create an ImplementationReference from C++ pointer
145 :
146 : @param pImpl
147 : The pointer to the C++ implementation type, which is
148 : queried for the template-parameterized UNO type.
149 :
150 : @param dummy
151 : Dummy parameter, to distinguish this contructor from the
152 : default unary one (which does not perform a
153 : QueryInterface)
154 : */
155 0 : ImplementationReference( ImplementationType* pImpl, CreateFromQuery ) :
156 : mxRef( static_cast<UnambiguousXInterfaceType*>(pImpl),
157 : ::com::sun::star::uno::UNO_QUERY ),
158 0 : mpImpl( pImpl )
159 : {
160 0 : }
161 :
162 : /** Factory method to create an ImplementationReference from
163 : C++ pointer.
164 :
165 : This is a static version of the constructor which creates
166 : an instance of an implementation type which is explicitly
167 : queried for the ImplementationReference's
168 : template-parameterized UNO type.
169 :
170 : @sample
171 : mpRef = mpRef.createFromQuery( new ImplementationType );
172 : */
173 0 : static ImplementationReference createFromQuery( ImplementationType* pImpl )
174 : {
175 0 : return ImplementationReference( pImpl, CreateFromQuery() );
176 : }
177 :
178 : /** Query whether the pointer is still valid.
179 :
180 : Hands off also from the implementation pointer if this
181 : returns false!
182 : */
183 0 : bool is() const { return mxRef.is(); }
184 :
185 : /** Get a pointer to the implementation object
186 :
187 : Compatibility method to get an auto_ptr-compatible
188 : interface
189 : */
190 94 : ImplementationType* get() { return mpImpl; }
191 : const ImplementationType* get() const { return mpImpl; }
192 :
193 : /** Release all references
194 :
195 : Compatibility method to get an auto_ptr-compatible
196 : interface
197 : */
198 102 : void reset() { dispose(); }
199 :
200 : /** Release all references
201 :
202 : This method releases the UNO interface reference, and
203 : clears the C++ pointer to NULL.
204 : */
205 102 : void dispose() { mxRef = NULL; mpImpl=NULL; }
206 :
207 0 : ImplementationType* operator->() { return mpImpl; }
208 0 : const ImplementationType* operator->() const { return mpImpl; }
209 :
210 : ImplementationType& operator*() { return *mpImpl; }
211 : const ImplementationType& operator*() const { return *mpImpl; }
212 :
213 : /// Access to the underlying UNO reference, without extra querying
214 18 : ::com::sun::star::uno::Reference< UnoInterfaceType > getRef() { return mxRef; }
215 :
216 : /// Access to the underlying UNO reference, without extra querying
217 0 : const ::com::sun::star::uno::Reference< UnoInterfaceType >& getRef() const { return mxRef; }
218 :
219 : // default destructor, copy constructor and assignment will do
220 : // ~ImplementationReference();
221 : // ImplementationReference( const ImplementationReference& );
222 : // ImplementationReference& operator= ( const ImplementationReference& );
223 :
224 : /** Comparison operator
225 :
226 : Object identity is defined to be identity of the
227 : implementation pointers. This is in general invalid when
228 : comparing pointers to UNO objects (ambiguous class
229 : hierarchies, optimizations in the bridges, etc.), but okay
230 : for raw C++ pointers (which is what's compared herein).
231 : */
232 : bool operator==( const ImplementationReference& rhs ) const
233 : {
234 : return mpImpl == rhs.mpImpl;
235 : }
236 :
237 : /** less-than operator
238 :
239 : Object order is defined to be the ordering of the
240 : implementation pointers. This is in general invalid when
241 : comparing pointers to UNO objects (ambiguous class
242 : hierarchies, optimizations in the bridges, etc.), but okay
243 : for raw C++ pointers (which is what's used herein).
244 :
245 : This ordering complies with STL's strict weak ordering
246 : concept.
247 : */
248 : bool operator<( const ImplementationReference& rhs ) const
249 : {
250 : return mpImpl < rhs.mpImpl;
251 : }
252 :
253 : private:
254 :
255 : // the interface, hard reference to prevent object from vanishing
256 : ::com::sun::star::uno::Reference< UnoInterfaceType > mxRef;
257 :
258 : // the c++ object, for our internal stuff
259 : ImplementationType* mpImpl;
260 :
261 : };
262 :
263 : }
264 :
265 : #endif // _COMPHELPER_IMPLEMENTATIONREFERENCE_HXX
266 :
267 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|