BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_objectbuffer.h
Go to the documentation of this file.
1/// @file bsls_objectbuffer.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_objectbuffer.h -*-C++-*-
8#ifndef INCLUDED_BSLS_OBJECTBUFFER
9#define INCLUDED_BSLS_OBJECTBUFFER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_objectbuffer bsls_objectbuffer
15/// @brief Provide raw buffer with size and alignment of user-specified type.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_objectbuffer
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_objectbuffer-purpose"> Purpose</a>
25/// * <a href="#bsls_objectbuffer-classes"> Classes </a>
26/// * <a href="#bsls_objectbuffer-description"> Description </a>
27/// * <a href="#bsls_objectbuffer-usage"> Usage </a>
28/// * <a href="#bsls_objectbuffer-example-1-creating-a-dynamic-array-of-objects"> Example 1: Creating a Dynamic Array of Objects </a>
29/// * <a href="#bsls_objectbuffer-example-2-containing-different-object-types"> Example 2: Containing Different Object Types </a>
30///
31/// # Purpose {#bsls_objectbuffer-purpose}
32/// Provide raw buffer with size and alignment of user-specified type.
33///
34/// # Classes {#bsls_objectbuffer-classes}
35///
36/// - bsls::ObjectBuffer: parameterized buffer aligned to hold specified type
37///
38/// @see bsls_alignmentfromtype
39///
40/// # Description {#bsls_objectbuffer-description}
41/// This component provides a templated buffer type,
42/// `bsls::ObjectBuffer`, that is compile-time sized and aligned to hold a
43/// specified object type. Defining a `bsls::ObjectBuffer<TYPE>` object does
44/// not cause the constructor for `TYPE` to be called. Similarly, destroying
45/// the object buffer does not call the destructor for `TYPE`. Instead, the
46/// user instantiates `bsls::ObjectBuffer` with a specific type, then constructs
47/// an object of that type within that buffer. When the object is no longer
48/// needed, the user must explicitly call its destructor. A
49/// `bsls::ObjectBuffer` can reside on the stack or within another object,
50/// including within a `union`.
51///
52/// Typically, a `bsls::ObjectBuffer` is used in situations where efficient
53/// (e.g., stack-based) storage is required but where straightforward
54/// initialization or destruction of an object is not possible. For example,
55/// `bsls::ObjectBuffer` can be used to construct an array where the number of
56/// used elements varies at run-time or where the element type does not have a
57/// default constructor. It can also be used to create a `union` containing
58/// non-POD element types.
59///
60/// ## Usage {#bsls_objectbuffer-usage}
61///
62///
63/// The examples below use a value-semantic string class, `my_String`, that can
64/// be constructed from a null-terminated string and contains a member, `c_str`,
65/// that returns a null-terminated string. `my_String` does not have a default
66/// constructor and thus cannot be used in C-style arrays or unions.
67///
68/// ### Example 1: Creating a Dynamic Array of Objects {#bsls_objectbuffer-example-1-creating-a-dynamic-array-of-objects}
69///
70///
71/// Here we use `bsls::ObjectBuffer` to create a variable-length array of
72/// `my_String` objects. For efficiency, the array is created on the stack as
73/// a fixed-sized array of `bsls::ObjectBuffer<my_String>` objects and the
74/// length is kept in a separate variable. Only `len` calls are made to the
75/// `my_String` constructor, with the unused array elements left as raw
76/// memory. An array directly containing `my_String` objects would not have
77/// been possible because `my_String` does not have a default constructor.
78///
79/// WARNING: the `manipulateStrings` function below is not exception-safe.
80/// If an exception is thrown anywhere within the function (e.g., from a
81/// constructor call), the destructor will not be called on the constructed
82/// string objects. This logic would typically be augmented with guard objects
83/// that call destructors in case of an exception.
84/// @code
85/// void manipulateStrings(const my_String *stringArray, int len)
86/// {
87/// assert(len <= 10);
88///
89/// bsls::ObjectBuffer<my_String> tempArray[10];
90/// for (int i = 0; i < len; ++i) {
91/// new (tempArray[i].buffer()) my_String(stringArray[i]);
92/// assert(stringArray[i] == tempArray[i].object())
93/// }
94///
95/// for (int i = 0; i < len; ++i)
96/// {
97/// my_String& s = tempArray[i].object();
98/// // ... String manipulations go here. 's' might be analyzed,
99/// // appended-to, passed to other functions, etc.
100/// }
101///
102/// while (len) {
103/// // Destroy strings. Although not critical to this example, we
104/// // follow the general rule of destroying the objects in reverse
105/// // order of their construction, thus mimicking the
106/// // compiler-generated destruction order for normal array objects.
107/// tempArray[--len].object().~my_String();
108/// }
109/// }
110///
111/// int main()
112/// {
113/// const my_String INARRAY[3] = {
114/// my_String("hello"),
115/// my_String("goodbye"),
116/// my_String("Bloomberg")
117/// };
118///
119/// manipulateStrings(INARRAY, 3);
120///
121/// return 0;
122/// }
123/// @endcode
124///
125/// ### Example 2: Containing Different Object Types {#bsls_objectbuffer-example-2-containing-different-object-types}
126///
127///
128/// Here we use `bsls::ObjectBuffer` to compose a variable-type object capable
129/// of holding a string or an integer:
130/// @code
131/// class my_Union {
132/// public:
133/// enum TypeTag { INT, STRING };
134///
135/// private:
136/// TypeTag d_type;
137/// union {
138/// int d_int;
139/// bsls::ObjectBuffer<my_String> d_string;
140/// };
141///
142/// public:
143/// my_Union(int i = 0) : d_type(INT) { d_int = i; } // IMPLICIT
144/// my_Union(const my_String& s) : d_type(STRING) { // IMPLICIT
145/// new (d_string.buffer()) my_String(s); }
146/// my_Union(const char *s) : d_type(STRING) { // IMPLICIT
147/// new (d_string.buffer()) my_String(s); }
148/// my_Union(const my_Union& rhs) : d_type(rhs.d_type) {
149/// if (INT == d_type) {
150/// d_int = rhs.d_int;
151/// }
152/// else {
153/// new (d_string.buffer()) my_String(rhs.d_string.object());
154/// }
155/// }
156/// ~my_Union() {
157/// if (STRING == d_type) d_string.object().~my_String(); }
158///
159/// my_Union& operator=(const my_Union& rhs) {
160/// if (INT == d_type) {
161/// if (INT == rhs.d_type) {
162/// d_int = rhs.d_int;
163/// }
164/// else { // if STRING == rhs.d_type
165/// new (d_string.buffer()) my_String(rhs.d_string.object());
166/// }
167/// }
168/// else { // if (STRING == d_type)
169/// if (INT == rhs.d_type) {
170/// d_string.object().~my_String();
171/// d_int = rhs.d_int;
172/// }
173/// else { // if STRING == rhs.d_type
174/// d_string.object() = rhs.d_string.object();
175/// }
176/// }
177/// d_type = rhs.d_type;
178/// return *this;
179/// }
180///
181/// TypeTag typeTag() const { return d_type; }
182///
183/// int asInt() const {
184/// return INT == d_type ?
185/// d_int : static_cast<int>(
186/// strtol(d_string.object().c_str(), 0, 0));
187/// }
188///
189/// my_String asString() const {
190/// if (INT == d_type) {
191/// char temp[15];
192/// sprintf(temp, "%d", d_int);
193/// return my_String(temp);
194/// }
195/// else {
196/// return d_string.object();
197/// }
198/// }
199/// };
200///
201/// int main()
202/// {
203/// assert(sizeof(bsls::ObjectBuffer<my_String>) == sizeof(my_String));
204///
205/// // Create a 'my_Union' object containing a string.
206/// const my_Union U1("hello");
207/// assert(my_Union::STRING == U1.typeTag());
208/// assert(0 == U1.asInt());
209/// assert("hello" == U1.asString());
210///
211/// // Create a 'my_Union' object containing an integer.
212/// const my_Union U2(123);
213/// assert(my_Union::INT == U2.typeTag());
214/// assert(123 == U2.asInt());
215/// assert("123" == U2.asString());
216///
217/// // Create a 'my_Union' object containing a string that can be
218/// // interpreted as an integer.
219/// const my_Union U3("0x456");
220/// assert(my_Union::STRING == U3.typeTag());
221/// assert(0x456 == U3.asInt());
222/// assert("0x456" == U3.asString());
223///
224/// // Copy-construct a 'my_Union' object containing a string.
225/// my_Union u4(U3);
226/// assert(my_Union::STRING == u4.typeTag());
227/// assert(0x456 == u4.asInt());
228/// assert("0x456" == u4.asString());
229///
230/// // Use assignment to change 'u4' from string to integer.
231/// u4 = U2;
232/// assert(my_Union::INT == u4.typeTag());
233/// assert(123 == u4.asInt());
234/// assert("123" == u4.asString());
235///
236/// return 0;
237/// }
238/// @endcode
239/// @}
240/** @} */
241/** @} */
242
243/** @addtogroup bsl
244 * @{
245 */
246/** @addtogroup bsls
247 * @{
248 */
249/** @addtogroup bsls_objectbuffer
250 * @{
251 */
252
253#include <bsls_alignmentfromtype.h>
254
255
256
257namespace bsls {
258
259 // ==================
260 // union ObjectBuffer
261 // ==================
262
263/// An instance of this union is a raw block of memory suitable for storing
264/// an object of type `TYPE`. Specifically, the size and alignment of this
265/// union exactly matches that of `TYPE`. A `TYPE` object can be
266/// constructed into an `ObjectBuffer` using the placement `new` operator
267/// and can be destroyed by explicitly calling its destructor, `~TYPE()`.
268/// It is the user's responsibility to perform this construction and
269/// destruction; an `ObjectBuffer` object does not manage the construction
270/// or destruction of any other objects.
271///
272/// Note that a collaboration is implied between `ObjectBuffer` and the
273/// user. An `ObjectBuffer` provides aligned memory and the user handles
274/// construction and destruction of the object contained within that memory.
275template <class TYPE>
277
278 private:
279 // DATA
280 // Buffer correctly sized and aligned for object of type 'TYPE'.
281 char d_buffer[sizeof(TYPE)];
282 typename AlignmentFromType<TYPE>::Type d_align;
283
284 public:
285 // CREATORS
286 // Note that we deliberately omit defining constructors and destructors in
287 // order to keep this union "POD-like". In particular, an 'ObjectBuffer'
288 // may be used as a member in another 'union'. Copying an 'ObjectBuffer'
289 // by assignment or copy construction will result in a bit-wise copy and
290 // will not invoke 'TYPE's assignment operator or copy constructor.
291
292 // MANIPULATORS
293
294 /// Return the address of the first byte of this object, cast to a
295 /// `TYPE *` pointer.
296 TYPE *address();
297
298 /// Return the address of the first byte of this object, cast to a
299 /// `char *` pointer.
300 char *buffer();
301
302 /// Return a modifiable reference to the `TYPE` object occupying this
303 /// buffer. The referenced object has undefined state unless a valid
304 /// `TYPE` object has been constructed in this buffer.
305 TYPE& object();
306
307 // ACCESSORS
308
309 /// Return the address of the first byte of this object, cast to a
310 /// `const TYPE *` pointer.
311 const TYPE *address() const;
312
313 /// Return the address of the first byte of this object, cast to a
314 /// `const char *` pointer.
315 const char *buffer() const;
316
317 /// Return a `const` reference to the `TYPE` object occupying this
318 /// buffer. The referenced object has undefined state unless a valid
319 /// `TYPE` object has been constructed in this buffer.
320 const TYPE& object() const;
321};
322
323// ============================================================================
324// INLINE FUNCTION DEFINITIONS
325// ============================================================================
326
327 // ------------------
328 // union ObjectBuffer
329 // ------------------
330
331// MANIPULATORS
332template <class TYPE>
333inline
335{
336 // A redundant cast to 'void *' persuades gcc/Solaris that there are no
337 // alignment issues to warn about.
338
339 return reinterpret_cast<TYPE *>(static_cast<void *>(d_buffer));
340}
341
342template <class TYPE>
343inline
345{
346 return d_buffer;
347}
348
349template <class TYPE>
350inline
352{
353 return *reinterpret_cast<TYPE *>(this);
354}
355
356// ACCESSORS
357template <class TYPE>
358inline
360{
361 // A redundant cast to 'const void *' persuades gcc/Solaris that there are
362 // no alignment issues to warn about.
363
364 return reinterpret_cast<const TYPE *>(static_cast<const void *>(d_buffer));
365}
366
367template <class TYPE>
368inline
369const char *ObjectBuffer<TYPE>::buffer() const
370{
371 return d_buffer;
372}
373
374template <class TYPE>
375inline
376const TYPE& ObjectBuffer<TYPE>::object() const
377{
378 return *reinterpret_cast<const TYPE *>(this);
379}
380
381} // close package namespace
382
383// ============================================================================
384// BACKWARD COMPATIBILITY
385// ============================================================================
386
387#ifndef BDE_OMIT_INTERNAL_DEPRECATED
388
389#ifdef bdes_ObjectBuffer
390#undef bdes_ObjectBuffer
391#endif
392/// This alias is defined for backward compatibility.
393#define bdes_ObjectBuffer bsls::ObjectBuffer
394
395#endif // BDE_OMIT_INTERNAL_DEPRECATED
396
397#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
398
399#ifdef bsls_ObjectBuffer
400#undef bsls_ObjectBuffer
401#endif
402/// This alias is defined for backward compatibility.
403#define bsls_ObjectBuffer bsls::ObjectBuffer
404
405#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
406
407
408
409#endif
410
411// ----------------------------------------------------------------------------
412// Copyright 2013 Bloomberg Finance L.P.
413//
414// Licensed under the Apache License, Version 2.0 (the "License");
415// you may not use this file except in compliance with the License.
416// You may obtain a copy of the License at
417//
418// http://www.apache.org/licenses/LICENSE-2.0
419//
420// Unless required by applicable law or agreed to in writing, software
421// distributed under the License is distributed on an "AS IS" BASIS,
422// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
423// See the License for the specific language governing permissions and
424// limitations under the License.
425// ----------------------------- END-OF-FILE ----------------------------------
426
427/** @} */
428/** @} */
429/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlt_iso8601util.h:691
AlignmentToType< VALUE >::Type Type
Definition bsls_alignmentfromtype.h:386
Definition bsls_objectbuffer.h:276
const TYPE & object() const
Definition bsls_objectbuffer.h:376
char * buffer()
Definition bsls_objectbuffer.h:344
const char * buffer() const
Definition bsls_objectbuffer.h:369
const TYPE * address() const
Definition bsls_objectbuffer.h:359
TYPE * address()
Definition bsls_objectbuffer.h:334
TYPE & object()
Definition bsls_objectbuffer.h:351