]> git.ipfire.org Git - thirdparty/gcc.git/blob - libcilkrts/include/cilk/reducer_string.h
9af65d553417c311b549d0417a54c06764e5305e
[thirdparty/gcc.git] / libcilkrts / include / cilk / reducer_string.h
1 /* reducer_string.h -*- C++ -*-
2 *
3 * Copyright (C) 2009-2016, Intel Corporation
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
30 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * *********************************************************************
34 *
35 * PLEASE NOTE: This file is a downstream copy of a file mainitained in
36 * a repository at cilkplus.org. Changes made to this file that are not
37 * submitted through the contribution process detailed at
38 * http://www.cilkplus.org/submit-cilk-contribution will be lost the next
39 * time that a new version is released. Changes only submitted to the
40 * GNU compiler collection or posted to the git repository at
41 * https://bitbucket.org/intelcilkruntime/intel-cilk-runtime.git are
42 * not tracked.
43 *
44 * We welcome your contributions to this open source project. Thank you
45 * for your assistance in helping us improve Cilk Plus.
46 */
47
48 /** @file reducer_string.h
49 *
50 * @brief Defines classes for doing parallel string creation by appending.
51 *
52 * @ingroup ReducersString
53 *
54 * @see ReducersString
55 */
56
57 #ifndef REDUCER_STRING_H_INCLUDED
58 #define REDUCER_STRING_H_INCLUDED
59
60 #include <cilk/reducer.h>
61 #include <string>
62 #include <list>
63
64 /** @defgroup ReducersString String Reducers
65 *
66 * String reducers allow the creation of a string by concatenating a set of
67 * strings or characters in parallel.
68 *
69 * @ingroup Reducers
70 *
71 * You should be familiar with @ref pagereducers "Intel(R) Cilk(TM) Plus reducers",
72 * described in file reducers.md, and particularly with @ref reducers_using,
73 * before trying to use the information in this file.
74 *
75 * @section redstring_usage Usage Example
76 *
77 * vector<Data> data;
78 * void expensive_string_computation(const Data& x, string& s);
79 * cilk::reducer<cilk::op_string> r;
80 * cilk_for (int i = 0; i != data.size(); ++i) {
81 * string temp;
82 * expensive_string_computation(data[i], temp);
83 * *r += temp;
84 * }
85 * string result;
86 * r.move_out(result);
87 *
88 * @section redstring_monoid The Monoid
89 *
90 * @subsection redstring_monoid_values Value Set
91 *
92 * The value set of a string reducer is the set of values of the class
93 * `std::basic_string<Char, Traits, Alloc>`, which we refer to as "the
94 * reducer's string type".
95 *
96 * @subsection redstring_monoid_operator Operator
97 *
98 * The operator of a string reducer is the string concatenation operator,
99 * defined by the "`+`" binary operator on the reducer's string type.
100 *
101 * @subsection redstring_monoid_identity Identity
102 *
103 * The identity value of a string reducer is the empty string, which is the
104 * value of the expression
105 * `std::basic_string<Char, Traits, Alloc>([allocator])`.
106 *
107 * @section redstring_operations Operations
108 *
109 * In the operation descriptions below, the type name `String` refers to the
110 * reducer's string type, `std::basic_string<Char, Traits, Alloc>`.
111 *
112 * @subsection redstring_constructors Constructors
113 *
114 * Any argument list which is valid for a `std::basic_string` constructor is
115 * valid for a string reducer constructor. The usual move-in constructor is
116 * also provided:
117 *
118 * reducer(move_in(String& variable))
119 *
120 * @subsection redstring_get_set Set and Get
121 *
122 * r.set_value(const String& value)
123 * const String& = r.get_value() const
124 * r.move_in(String& variable)
125 * r.move_out(String& variable)
126 *
127 * @subsection redstring_initial Initial Values
128 *
129 * A string reducer with no constructor arguments, or with only an allocator
130 * argument, will initially contain the identity value, an empty string.
131 *
132 * @subsection redstring_view_ops View Operations
133 *
134 * *r += a
135 * r->append(a)
136 * r->append(a, b)
137 * r->push_back(a)
138 *
139 * These operations on string reducer views are the same as the corresponding
140 * operations on strings.
141 *
142 * @section redstring_performance Performance Considerations
143 *
144 * String reducers work by creating a string for each view, collecting those
145 * strings in a list, and then concatenating them into a single result string
146 * at the end of the computation. This last step takes place in serial code,
147 * and necessarily takes time proportional to the length of the result string.
148 * Thus, a parallel string reducer cannot actually speed up the time spent
149 * directly creating the string. This trivial example would probably be slower
150 * (because of reducer overhead) than the corresponding serial code:
151 *
152 * vector<string> a;
153 * reducer<op_string> r;
154 * cilk_for (int i = 0; i != a.length(); ++i) {
155 * *r += a[i];
156 * }
157 * string result;
158 * r.move_out(result);
159 *
160 * What a string reducer _can_ do is to allow the _remainder_ of the
161 * computation to be done in parallel, without having to worry about managing
162 * the string computation.
163 *
164 * The strings for new views are created (by the view identity constructor)
165 * using the same allocator as the string that was created when the reducer
166 * was constructed. Note that this allocator is determined when the reducer is
167 * constructed. The following two examples may have very different behavior:
168 *
169 * string<Char, Traits, Allocator> a_string;
170 *
171 * reducer< op_string<Char, Traits, Allocator> reducer1(move_in(a_string));
172 * ... parallel computation ...
173 * reducer1.move_out(a_string);
174 *
175 * reducer< op_string<Char, Traits, Allocator> reducer2;
176 * reducer2.move_in(a_string);
177 * ... parallel computation ...
178 * reducer2.move_out(a_string);
179 *
180 * * `reducer1` will be constructed with the same allocator as `a_string`,
181 * because the string was specified in the constructor. The `move_in`
182 * and `move_out` can therefore be done with a `swap` in constant time.
183 * * `reducer2` will be constructed with a _default_ allocator of type
184 * `Allocator`, which may not be the same as the allocator of `a_string`.
185 * Therefore, the `move_in` and `move_out` may have to be done with a copy
186 * in _O(N)_ time.
187 *
188 * (All instances of an allocator type with no internal state (like
189 * `std::allocator`) are "the same". You only need to worry about the "same
190 * allocator" issue when you create string reducers with custom allocator
191 * types.)
192 *
193 * @section redstring_types Type and Operator Requirements
194 *
195 * `std::basic_string<Char, Traits, Alloc>` must be a valid type.
196 */
197
198 namespace cilk {
199
200 /** @ingroup ReducersString */
201 //@{
202
203 /** The string append reducer view class.
204 *
205 * This is the view class for reducers created with
206 * `cilk::reducer< cilk::op_basic_string<Char, Traits, Allocator> >`. It holds
207 * the accumulator variable for the reduction, and allows only append
208 * operations to be performed on it.
209 *
210 * @note The reducer "dereference" operation (`reducer::operator *()`)
211 * yields a reference to the view. Thus, for example, the view class's
212 * `append` operation would be used in an expression like
213 * `r->append(a)`, where `r` is a string append reducer variable.
214 *
215 * @tparam Char The string element type (not the string type).
216 * @tparam Traits The character traits type.
217 * @tparam Alloc The string allocator type.
218 *
219 * @see ReducersString
220 * @see op_basic_string
221 */
222 template<typename Char, typename Traits, typename Alloc>
223 class op_basic_string_view
224 {
225 typedef std::basic_string<Char, Traits, Alloc> string_type;
226 typedef std::list<string_type> list_type;
227 typedef typename string_type::size_type size_type;
228
229 // The view's value is represented by a list of strings and a single
230 // string. The value is the concatenation of the strings in the list with
231 // the single string at the end. All string operations apply to the single
232 // string; reduce operations cause lists of partial strings from multiple
233 // strands to be combined.
234 //
235 mutable string_type m_string;
236 mutable list_type m_list;
237
238 // Before returning the value of the reducer, concatenate all the strings
239 // in the list with the single string.
240 //
241 void flatten() const
242 {
243 if (m_list.empty()) return;
244
245 typename list_type::iterator i;
246
247 size_type len = m_string.size();
248 for (i = m_list.begin(); i != m_list.end(); ++i)
249 len += i->size();
250
251 string_type result(get_allocator());
252 result.reserve(len);
253
254 for (i = m_list.begin(); i != m_list.end(); ++i)
255 result += *i;
256 m_list.clear();
257
258 result += m_string;
259 result.swap(m_string);
260 }
261
262 public:
263
264 /** @name Monoid support.
265 */
266 //@{
267
268 /// Required by @ref monoid_with_view
269 typedef string_type value_type;
270
271 /// Required by @ref op_string
272 Alloc get_allocator() const
273 {
274 return m_string.get_allocator();
275 }
276
277 /** Reduces the views of two strands.
278 *
279 * This function is invoked by the @ref op_basic_string monoid to combine
280 * the views of two strands when the right strand merges with the left
281 * one. It appends the value contained in the right-strand view to the
282 * value contained in the left-strand view, and leaves the value in the
283 * right-strand view undefined.
284 *
285 * @param right A pointer to the right-strand view. (`this` points to
286 * the left-strand view.)
287 *
288 * @note Used only by the @ref op_basic_string monoid to implement the
289 * monoid reduce operation.
290 */
291 void reduce(op_basic_string_view* right)
292 {
293 if (!right->m_string.empty() || !right->m_list.empty()) {
294 // (list, string) + (right_list, right_string) =>
295 // (list + {string} + right_list, right_string)
296 if (!m_string.empty()) {
297 // simulate m_list.push_back(std::move(m_string))
298 m_list.push_back(string_type(get_allocator()));
299 m_list.back().swap(m_string);
300 }
301 m_list.splice(m_list.end(), right->m_list);
302 m_string.swap(right->m_string);
303 }
304 }
305
306 //@}
307
308 /** @name Passes constructor arguments to the string constructor.
309 */
310 //@{
311
312 op_basic_string_view() : m_string() {}
313
314 template <typename T1>
315 op_basic_string_view(const T1& x1) : m_string(x1) {}
316
317 template <typename T1, typename T2>
318 op_basic_string_view(const T1& x1, const T2& x2) : m_string(x1, x2) {}
319
320 template <typename T1, typename T2, typename T3>
321 op_basic_string_view(const T1& x1, const T2& x2, const T3& x3) : m_string(x1, x2, x3) {}
322
323 template <typename T1, typename T2, typename T3, typename T4>
324 op_basic_string_view(const T1& x1, const T2& x2, const T3& x3, const T4& x4) :
325 m_string(x1, x2, x3, x4) {}
326
327 //@}
328
329 /** Move-in constructor.
330 */
331 explicit op_basic_string_view(move_in_wrapper<value_type> w)
332 : m_string(w.value().get_allocator())
333 {
334 m_string.swap(w.value());
335 }
336
337 /** @name @ref reducer support.
338 */
339 //@{
340
341 void view_move_in(string_type& s)
342 {
343 m_list.clear();
344 if (m_string.get_allocator() == s.get_allocator())
345 // Equal allocators. Do a (fast) swap.
346 m_string.swap(s);
347 else
348 // Unequal allocators. Do a (slow) copy.
349 m_string = s;
350 s.clear();
351 }
352
353 void view_move_out(string_type& s)
354 {
355 flatten();
356 if (m_string.get_allocator() == s.get_allocator())
357 // Equal allocators. Do a (fast) swap.
358 m_string.swap(s);
359 else
360 // Unequal allocators. Do a (slow) copy.
361 s = m_string;
362 m_string.clear();
363 }
364
365 void view_set_value(const string_type& s)
366 { m_list.clear(); m_string = s; }
367
368 string_type const& view_get_value() const
369 { flatten(); return m_string; }
370
371 typedef string_type const& return_type_for_get_value;
372
373 string_type & view_get_reference()
374 { flatten(); return m_string; }
375
376 string_type const& view_get_reference() const
377 { flatten(); return m_string; }
378
379 //@}
380
381 /** @name View modifier operations.
382 *
383 * @details These simply wrap the corresponding operations on the underlying string.
384 */
385 //@{
386
387 template <typename T>
388 op_basic_string_view& operator +=(const T& x)
389 { m_string += x; return *this; }
390
391 template <typename T1>
392 op_basic_string_view& append(const T1& x1)
393 { m_string.append(x1); return *this; }
394
395 template <typename T1, typename T2>
396 op_basic_string_view& append(const T1& x1, const T2& x2)
397 { m_string.append(x1, x2); return *this; }
398
399 template <typename T1, typename T2, typename T3>
400 op_basic_string_view& append(const T1& x1, const T2& x2, const T3& x3)
401 { m_string.append(x1, x2, x3); return *this; }
402
403 void push_back(const Char x) { m_string.push_back(x); }
404
405 //@}
406 };
407
408
409 /** String append monoid class. Instantiate the cilk::reducer template class
410 * with an op_basic_string monoid to create a string append reducer class. For
411 * example, to concatenate a collection of standard strings:
412 *
413 * cilk::reducer< cilk::op_basic_string<char> > r;
414 *
415 * @tparam Char The string element type (not the string type).
416 * @tparam Traits The character traits type.
417 * @tparam Alloc The string allocator type.
418 * @tparam Align If `false` (the default), reducers instantiated on this
419 * monoid will be naturally aligned (the Intel Cilk Plus library 1.0
420 * behavior). If `true`, reducers instantiated on this monoid
421 * will be cache-aligned for binary compatibility with
422 * reducers in Intel Cilk Plus library version 0.9.
423 *
424 * @see ReducersString
425 * @see op_basic_string_view
426 * @see reducer_basic_string
427 * @see op_string
428 * @see op_wstring
429 */
430 template<typename Char,
431 typename Traits = std::char_traits<Char>,
432 typename Alloc = std::allocator<Char>,
433 bool Align = false>
434 class op_basic_string :
435 public monoid_with_view< op_basic_string_view<Char, Traits, Alloc>, Align >
436 {
437 typedef monoid_with_view< op_basic_string_view<Char, Traits, Alloc>, Align >
438 base;
439 typedef provisional_guard<typename base::view_type> view_guard;
440
441 Alloc m_allocator;
442
443 public:
444
445 /** View type of the monoid.
446 */
447 typedef typename base::view_type view_type;
448
449 /** Constructor.
450 *
451 * There is no default constructor for string monoids, because the
452 * allocator must always be specified.
453 *
454 * @param allocator The list allocator to be used when
455 * identity-constructing new views.
456 */
457 op_basic_string(const Alloc& allocator = Alloc()) : m_allocator(allocator)
458 {}
459
460 /** Creates an identity view.
461 *
462 * String view identity constructors take the string allocator as an
463 * argument.
464 *
465 * @param v The address of the uninitialized memory in which the view
466 * will be constructed.
467 */
468 void identity(view_type *v) const
469 { ::new((void*) v) view_type(m_allocator); }
470
471 /** @name Construct functions
472 *
473 * A string append reduction monoid must have a copy of the allocator of
474 * the leftmost view's string, so that it can use it in the `identity`
475 * operation. This, in turn, requires that string reduction monoids have a
476 * specialized `construct()` function.
477 *
478 * All string reducer monoid `construct()` functions first construct the
479 * leftmost view, using the arguments that were passed in from the reducer
480 * constructor. They then call the view's `get_allocator()` function to
481 * get the string allocator from the string in the leftmost view, and pass
482 * that to the monoid constructor.
483 */
484 //@{
485
486 static void construct(op_basic_string* monoid, view_type* view)
487 {
488 view_guard vg( new((void*) view) view_type() );
489 vg.confirm_if(
490 new((void*) monoid) op_basic_string(view->get_allocator()) );
491 }
492
493 template <typename T1>
494 static void construct(op_basic_string* monoid, view_type* view,
495 const T1& x1)
496 {
497 view_guard vg( new((void*) view) view_type(x1) );
498 vg.confirm_if(
499 new((void*) monoid) op_basic_string(view->get_allocator()) );
500 }
501
502 template <typename T1, typename T2>
503 static void construct(op_basic_string* monoid, view_type* view,
504 const T1& x1, const T2& x2)
505 {
506 view_guard vg( new((void*) view) view_type(x1, x2) );
507 vg.confirm_if(
508 new((void*) monoid) op_basic_string(view->get_allocator()) );
509 }
510
511 template <typename T1, typename T2, typename T3>
512 static void construct(op_basic_string* monoid, view_type* view,
513 const T1& x1, const T2& x2, const T3& x3)
514 {
515 view_guard vg( new((void*) view) view_type(x1, x2, x3) );
516 vg.confirm_if(
517 new((void*) monoid) op_basic_string(view->get_allocator()) );
518 }
519
520 template <typename T1, typename T2, typename T3, typename T4>
521 static void construct(op_basic_string* monoid, view_type* view,
522 const T1& x1, const T2& x2, const T3& x3,
523 const T4& x4)
524 {
525 view_guard vg( new((void*) view) view_type(x1, x2, x3, x4) );
526 vg.confirm_if(
527 new((void*) monoid) op_basic_string(view->get_allocator()) );
528 }
529
530 //@}
531 };
532
533
534 /** Convenience typedef for 8-bit strings
535 */
536 typedef op_basic_string<char> op_string;
537
538 /** Convenience typedef for 16-bit strings
539 */
540 typedef op_basic_string<wchar_t> op_wstring;
541
542
543 /** Deprecated string append reducer class.
544 *
545 * reducer_basic_string is the same as @ref reducer<@ref op_basic_string>,
546 * except that reducer_basic_string is a proxy for the contained view, so that
547 * accumulator variable update operations can be applied directly to the
548 * reducer. For example, a value is appended to a `reducer<%op_basic_string>`
549 * with `r->push_back(a)`, but a value can be appended to a `%reducer_opand`
550 * with `r.push_back(a)`.
551 *
552 * @deprecated Users are strongly encouraged to use `reducer<monoid>`
553 * reducers rather than the old wrappers like reducer_basic_string.
554 * The `reducer<monoid>` reducers show the reducer/monoid/view
555 * architecture more clearly, are more consistent in their
556 * implementation, and present a simpler model for new
557 * user-implemented reducers.
558 *
559 * @note Implicit conversions are provided between `%reducer_basic_string`
560 * and `reducer<%op_basic_string>`. This allows incremental code
561 * conversion: old code that used `%reducer_basic_string` can pass a
562 * `%reducer_basic_string` to a converted function that now expects a
563 * pointer or reference to a `reducer<%op_basic_string>`, and vice
564 * versa.
565 *
566 * @tparam Char The string element type (not the string type).
567 * @tparam Traits The character traits type.
568 * @tparam Alloc The string allocator type.
569 *
570 * @see op_basic_string
571 * @see reducer
572 * @see ReducersString
573 */
574 template<typename Char,
575 typename Traits = std::char_traits<Char>,
576 typename Alloc = std::allocator<Char> >
577 class reducer_basic_string :
578 public reducer< op_basic_string<Char, Traits, Alloc, true> >
579 {
580 typedef reducer< op_basic_string<Char, Traits, Alloc, true> > base;
581 using base::view;
582 public:
583
584 /// The reducer's string type.
585 typedef typename base::value_type string_type;
586
587 /// The reducer's primitive component type.
588 typedef Char basic_value_type;
589
590 /// The string size type.
591 typedef typename string_type::size_type size_type;
592
593 /// The view type for the reducer.
594 typedef typename base::view_type View;
595
596 /// The monoid type for the reducer.
597 typedef typename base::monoid_type Monoid;
598
599
600 /** @name Constructors
601 */
602 //@{
603
604 /** @name Forward constructor calls to the base class.
605 *
606 * All basic_string constructor forms are supported.
607 */
608 //@{
609 reducer_basic_string() {}
610
611 template <typename T1>
612 reducer_basic_string(const T1& x1) :
613 base(x1) {}
614
615 template <typename T1, typename T2>
616 reducer_basic_string(const T1& x1, const T2& x2) :
617 base(x1, x2) {}
618
619 template <typename T1, typename T2, typename T3>
620 reducer_basic_string(const T1& x1, const T2& x2, const T3& x3) :
621 base(x1, x2, x3) {}
622
623 template <typename T1, typename T2, typename T3, typename T4>
624 reducer_basic_string(const T1& x1, const T2& x2, const T3& x3, const T4& x4) :
625 base(x1, x2, x3, x4) {}
626 //@}
627
628 /** Allows mutable access to the string within the current view.
629 *
630 * @warning If this method is called before the parallel calculation is
631 * complete, the string returned by this method will be a
632 * partial result.
633 *
634 * @returns A mutable reference to the string within the current view.
635 */
636 string_type &get_reference()
637 { return view().view_get_reference(); }
638
639 /** Allows read-only access to the string within the current view.
640 *
641 * @warning If this method is called before the parallel calculation is
642 * complete, the string returned by this method will be a
643 * partial result.
644 *
645 * @returns A const reference to the string within the current view.
646 */
647 string_type const &get_reference() const
648 { return view().view_get_reference(); }
649
650 /** @name Appends to the string.
651 *
652 * These operations are simply forwarded to the view.
653 */
654 //@{
655 void append(const Char *ptr)
656 { view().append(ptr); }
657 void append(const Char *ptr, size_type count)
658 { view().append(ptr, count); }
659 void append(const string_type &str, size_type offset, size_type count)
660 { view().append(str, offset, count); }
661 void append(const string_type &str)
662 { view().append(str); }
663 void append(size_type count, Char ch)
664 { view().append(count, ch); }
665
666 // Appends to the string
667 reducer_basic_string<Char, Traits, Alloc> &operator+=(Char ch)
668 { view() += ch; return *this; }
669 reducer_basic_string<Char, Traits, Alloc> &operator+=(const Char *ptr)
670 { view() += ptr; return *this; }
671 reducer_basic_string<Char, Traits, Alloc> &operator+=(const string_type &right)
672 { view() += right; return *this; }
673 //@}
674
675 /** @name Dereference
676 * @details Dereferencing a wrapper is a no-op. It simply returns the
677 * wrapper. Combined with the rule that the wrapper forwards view
678 * operations to its contained view, this means that view operations can
679 * be written the same way on reducers and wrappers, which is convenient
680 * for incrementally converting old code using wrappers to use reducers
681 * instead. That is:
682 *
683 * reducer<op_string> r;
684 * r->push_back(a); // r-> returns the view
685 * // push_back() is a view member function
686 *
687 * reducer_string w;
688 * w->push_back(a); // *w returns the wrapper
689 * // push_back() is a wrapper member function
690 * // that calls the corresponding view function
691 */
692 //@{
693 reducer_basic_string& operator*() { return *this; }
694 reducer_basic_string const& operator*() const { return *this; }
695
696 reducer_basic_string* operator->() { return this; }
697 reducer_basic_string const* operator->() const { return this; }
698 //@}
699
700 /** @name Upcast
701 * @details In Intel Cilk Plus library 0.9, reducers were always cache-aligned.
702 * In library 1.0, reducer cache alignment is optional. By default,
703 * reducers are unaligned (i.e., just naturally aligned), but legacy
704 * wrappers inherit from cache-aligned reducers for binary compatibility.
705 *
706 * This means that a wrapper will automatically be upcast to its aligned
707 * reducer base class. The following conversion operators provide
708 * pseudo-upcasts to the corresponding unaligned reducer class.
709 */
710 //@{
711 operator reducer< op_basic_string<Char, Traits, Alloc, false> >& ()
712 {
713 return *reinterpret_cast< reducer<
714 op_basic_string<Char, Traits, Alloc, false> >*
715 >(this);
716 }
717 operator const reducer< op_basic_string<Char, Traits, Alloc, false> >& () const
718 {
719 return *reinterpret_cast< const reducer<
720 op_basic_string<Char, Traits, Alloc, false> >*
721 >(this);
722 }
723 //@}
724 };
725
726
727 /** Convenience typedef for 8-bit strings
728 */
729 typedef reducer_basic_string<char> reducer_string;
730
731 /** Convenience typedef for 16-bit strings
732 */
733 typedef reducer_basic_string<wchar_t> reducer_wstring;
734
735 /// @cond internal
736
737 /// @cond internal
738 /** Metafunction specialization for reducer conversion.
739 *
740 * This specialization of the @ref legacy_reducer_downcast template class
741 * defined in reducer.h causes the `reducer< op_basic_string<Char> >` class to
742 * have an `operator reducer_basic_string<Char>& ()` conversion operator that
743 * statically downcasts the `reducer<op_basic_string>` to the corresponding
744 * `reducer_basic_string` type. (The reverse conversion, from
745 * `reducer_basic_string` to `reducer<op_basic_string>`, is just an upcast,
746 * which is provided for free by the language.)
747 *
748 * @ingroup ReducersString
749 */
750 template<typename Char, typename Traits, typename Alloc, bool Align>
751 struct legacy_reducer_downcast<
752 reducer<op_basic_string<Char, Traits, Alloc, Align> > >
753 {
754 typedef reducer_basic_string<Char, Traits, Alloc> type;
755 };
756
757 /// @endcond
758
759 //@}
760
761 } // namespace cilk
762
763 #endif // REDUCER_STRING_H_INCLUDED