1 #ifndef _GLIBMM_ARRAYHANDLE_H
2 #define _GLIBMM_ARRAYHANDLE_H
3 
4 /* Copyright (C) 2002 The gtkmm Development Team
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <glibmmconfig.h>
21 #include <glibmm/containerhandle_shared.h>
22 
23 namespace Glib
24 {
25 
26 namespace Container_Helpers
27 {
28 
29 #ifndef DOXYGEN_SHOULD_SKIP_THIS
30 
31 /* Count the number of elements in a 0-terminated sequence.
32  */
33 template <class T>
34 inline std::size_t
compute_array_size(const T * array)35 compute_array_size(const T* array)
36 {
37   const T* pend = array;
38 
39   while (*pend)
40     ++pend;
41 
42   return (pend - array);
43 }
44 
45 /* Allocate and fill a 0-terminated array.  The size argument
46  * specifies the number of elements in the input sequence.
47  */
48 template <class For, class Tr>
49 typename Tr::CType*
create_array(For pbegin,std::size_t size,Tr)50 create_array(For pbegin, std::size_t size, Tr)
51 {
52   using CType = typename Tr::CType;
53 
54   CType* const array = static_cast<CType*>(g_malloc((size + 1) * sizeof(CType)));
55   CType* const array_end = array + size;
56 
57   for (CType* pdest = array; pdest != array_end; ++pdest)
58   {
59     // Use & to force a warning if the iterator returns a temporary object.
60     *pdest = Tr::to_c_type(*&*pbegin);
61     ++pbegin;
62   }
63 
64   *array_end = CType();
65   return array;
66 }
67 
68 template <class For>
69 gboolean*
create_bool_array(For pbegin,std::size_t size)70 create_bool_array(For pbegin, std::size_t size)
71 {
72   gboolean* const array(static_cast<gboolean*>(g_malloc((size + 1) * sizeof(gboolean))));
73   gboolean* const array_end(array + size);
74 
75   for (gboolean* pdest(array); pdest != array_end; ++pdest)
76   {
77     *pdest = *pbegin;
78     ++pbegin;
79   }
80 
81   *array_end = false;
82   return array;
83 }
84 
85 /* Convert from any container that supports forward
86  * iterators and has a size() method.
87  */
88 template <class Tr, class Cont>
89 struct ArraySourceTraits
90 {
91   using CType = typename Tr::CType;
92 
get_sizeArraySourceTraits93   static std::size_t get_size(const Cont& cont) { return cont.size(); }
94 
get_dataArraySourceTraits95   static const CType* get_data(const Cont& cont, std::size_t size)
96   {
97     return Glib::Container_Helpers::create_array(cont.begin(), size, Tr());
98   }
99 
100   static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
101 };
102 
103 // source traits for bools.
104 template <class Cont>
105 struct BoolArraySourceTraits
106 {
107   using CType = gboolean;
108 
get_sizeBoolArraySourceTraits109   static std::size_t get_size(const Cont& cont) { return cont.size(); }
110 
get_dataBoolArraySourceTraits111   static const CType* get_data(const Cont& cont, std::size_t size)
112   {
113     return Glib::Container_Helpers::create_bool_array(cont.begin(), size);
114   }
115 
116   static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
117 };
118 /* Convert from a 0-terminated array.  The Cont argument must be a pointer
119  * to the first element.  Note that only arrays of the C type are supported.
120  */
121 template <class Tr, class Cont>
122 struct ArraySourceTraits<Tr, Cont*>
123 {
124   using CType = typename Tr::CType;
125 
126   static std::size_t get_size(const CType* array)
127   {
128     return (array) ? Glib::Container_Helpers::compute_array_size(array) : 0;
129   }
130 
131   static const CType* get_data(const CType* array, std::size_t) { return array; }
132 
133   static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_NONE;
134 };
135 
136 template <class Tr, class Cont>
137 struct ArraySourceTraits<Tr, const Cont*> : ArraySourceTraits<Tr, Cont*>
138 {
139 };
140 
141 /* Convert from a 0-terminated array.  The Cont argument must be a pointer
142  * to the first element.  Note that only arrays of the C type are supported.
143  * For consistency, the array must be 0-terminated, even though the array
144  * size is known at compile time.
145  */
146 template <class Tr, class Cont, std::size_t N>
147 struct ArraySourceTraits<Tr, Cont[N]>
148 {
149   using CType = typename Tr::CType;
150 
151   static std::size_t get_size(const CType*) { return (N - 1); }
152 
153   static const CType* get_data(const CType* array, std::size_t) { return array; }
154 
155   static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_NONE;
156 };
157 
158 template <class Tr, class Cont, std::size_t N>
159 struct ArraySourceTraits<Tr, const Cont[N]> : ArraySourceTraits<Tr, Cont[N]>
160 {
161 };
162 
163 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
164 
165 /**
166  * @ingroup ContHelpers
167  */
168 template <class Tr>
169 class ArrayHandleIterator
170 {
171 public:
172   using CppType = typename Tr::CppType;
173   using CType = typename Tr::CType;
174 
175   using iterator_category = std::random_access_iterator_tag;
176   using value_type = CppType;
177   using difference_type = std::ptrdiff_t;
178   using reference = value_type;
179   using pointer = void;
180 
181   explicit inline ArrayHandleIterator(const CType* pos);
182 
183   inline value_type operator*() const;
184   inline value_type operator[](difference_type offset) const;
185 
186   inline ArrayHandleIterator<Tr>& operator++();
187   inline const ArrayHandleIterator<Tr> operator++(int);
188   // these are needed by msvc 2005 when using deque.
189   inline ArrayHandleIterator<Tr>& operator--();
190   inline const ArrayHandleIterator<Tr> operator--(int);
191 
192   // All this random access stuff is only there because STL algorithms
193   // usually have optimized specializations for random access iterators,
194   // and we don't want to give away efficiency for nothing.
195   //
196   inline ArrayHandleIterator<Tr>& operator+=(difference_type rhs);
197   inline ArrayHandleIterator<Tr>& operator-=(difference_type rhs);
198   inline const ArrayHandleIterator<Tr> operator+(difference_type rhs) const;
199   inline const ArrayHandleIterator<Tr> operator-(difference_type rhs) const;
200   inline difference_type operator-(const ArrayHandleIterator<Tr>& rhs) const;
201 
202   inline bool operator==(const ArrayHandleIterator<Tr>& rhs) const;
203   inline bool operator!=(const ArrayHandleIterator<Tr>& rhs) const;
204   inline bool operator<(const ArrayHandleIterator<Tr>& rhs) const;
205   inline bool operator>(const ArrayHandleIterator<Tr>& rhs) const;
206   inline bool operator<=(const ArrayHandleIterator<Tr>& rhs) const;
207   inline bool operator>=(const ArrayHandleIterator<Tr>& rhs) const;
208 
209 private:
210   const CType* pos_;
211 };
212 
213 } // namespace Container_Helpers
214 
215 // TODO: When we can break ABI, remove this and replace uses of it with std::vector.
216 // We cannot deprecate it yet, because we cannot easily deprecate methods that use it
217 //- for instance, we cannot just override methods that use it as a return type.
218 
219 /** This is an intermediate type. When a method takes this, or returns this, you
220  * should use a standard C++ container of your choice, such as std::list or
221  * std::vector.
222  *
223  * However, this is not used in new API. We now prefer to just use std::vector,
224  * which is less flexibile, but makes the API clearer.
225  *
226  * @ingroup ContHandles
227  */
228 template <class T, class Tr = Glib::Container_Helpers::TypeTraits<T>>
229 class ArrayHandle
230 {
231 public:
232   using CppType = typename Tr::CppType;
233   using CType = typename Tr::CType;
234 
235   using value_type = CppType;
236   using size_type = std::size_t;
237   using difference_type = std::ptrdiff_t;
238 
239   using const_iterator = Glib::Container_Helpers::ArrayHandleIterator<Tr>;
240   using iterator = Glib::Container_Helpers::ArrayHandleIterator<Tr>;
241 
242   template <class Cont>
243   inline ArrayHandle(const Cont& container);
244 
245   // Take over ownership of an array created by GTK+ functions.
246   inline ArrayHandle(const CType* array, std::size_t array_size, Glib::OwnershipType ownership);
247   inline ArrayHandle(const CType* array, Glib::OwnershipType ownership);
248 
249   // Copying clears the ownership flag of the source handle.
250   inline ArrayHandle(const ArrayHandle<T, Tr>& other);
251 
252   ~ArrayHandle() noexcept;
253 
254   inline const_iterator begin() const;
255   inline const_iterator end() const;
256 
257   template <class U>
258   inline operator std::vector<U>() const;
259   template <class U>
260   inline operator std::deque<U>() const;
261   template <class U>
262   inline operator std::list<U>() const;
263 
264   template <class Cont>
265   inline void assign_to(Cont& container) const;
266 
267   template <class Out>
268   inline void copy(Out pdest) const;
269 
270   inline const CType* data() const;
271   inline std::size_t size() const;
272   inline bool empty() const;
273 
274 private:
275   std::size_t size_;
276   const CType* parray_;
277   mutable Glib::OwnershipType ownership_;
278 
279   // No copy assignment.
280   ArrayHandle<T, Tr>& operator=(const ArrayHandle<T, Tr>&);
281 };
282 
283 template <>
284 class GLIBMM_API ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>
285 {
286 public:
287   using Me = ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>;
288   using Tr = Container_Helpers::TypeTraits<bool>;
289 
290   using CppType = Tr::CppType;
291   using CType = Tr::CType;
292 
293   using value_type = CppType;
294   using size_type = std::size_t;
295   using difference_type = std::ptrdiff_t;
296 
297   using const_iterator = Glib::Container_Helpers::ArrayHandleIterator<Tr>;
298   using iterator = Glib::Container_Helpers::ArrayHandleIterator<Tr>;
299 
300   template <class Cont>
301   inline ArrayHandle(const Cont& container);
302 
303   // Take over ownership of an array created by GTK+ functions.
304   inline ArrayHandle(const CType* array, std::size_t array_size, Glib::OwnershipType ownership);
305   inline ArrayHandle(const CType* array, Glib::OwnershipType ownership);
306 
307   // Copying clears the ownership flag of the source handle.
308   inline ArrayHandle(const Me& other);
309 
310   ~ArrayHandle() noexcept;
311 
312   inline const_iterator begin() const;
313   inline const_iterator end() const;
314 
315   // this is inside class definition, so msvc 2005, 2008 and 2010 can compile this code.
316   template <class U>
317   inline operator std::vector<U>() const
318   {
319 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
320     return std::vector<U>(this->begin(), this->end());
321 #else
322     std::vector<U> temp;
323     temp.reserve(this->size());
324     Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
325     return temp;
326 #endif
327   }
328 
329   // this is inside class definition, so msvc 2005, 2008 and 2010 can compile this code.
330   template <class U>
331   inline operator std::deque<U>() const
332   {
333 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
334     return std::deque<U>(this->begin(), this->end());
335 #else
336     std::deque<U> temp;
337     Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
338     return temp;
339 #endif
340   }
341 
342   // this is inside class definition, so msvc 2005, 2008 and 2010 can compile this code.
343   template <class U>
344   inline operator std::list<U>() const
345   {
346 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
347     return std::list<U>(this->begin(), this->end());
348 #else
349     std::list<U> temp;
350     Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
351     return temp;
352 #endif
353   }
354 
355   template <class Cont>
356   inline void assign_to(Cont& container) const;
357 
358   template <class Out>
359   inline void copy(Out pdest) const;
360 
361   inline const CType* data() const;
362   inline std::size_t size() const;
363   inline bool empty() const;
364 
365 private:
366   std::size_t size_;
367   const CType* parray_;
368   mutable Glib::OwnershipType ownership_;
369 
370   // No copy assignment.
371   Me& operator=(const Me&);
372 };
373 
374 // TODO: Remove this when we can break glibmm API.
375 /** If a method takes this as an argument, or has this as a return type, then you can use a standard
376  * container such as std::list<Glib::ustring> or std::vector<Glib::ustring>.
377  *
378  *
379  * However, this is not used in new API. We now prefer to just use std::vector,
380  * which is less flexibile, but makes the API clearer.
381  *
382  * @ingroup ContHandles
383  */
384 using StringArrayHandle = ArrayHandle<Glib::ustring>;
385 
386 /***************************************************************************/
387 /*  Inline implementation                                                  */
388 /***************************************************************************/
389 
390 #ifndef DOXYGEN_SHOULD_SKIP_THIS
391 
392 namespace Container_Helpers
393 {
394 
395 /**** Glib::Container_Helpers::ArrayHandleIterator<> ***********************/
396 
397 template <class Tr>
398 inline ArrayHandleIterator<Tr>::ArrayHandleIterator(const CType* pos) : pos_(pos)
399 {
400 }
401 
402 template <class Tr>
403 inline typename ArrayHandleIterator<Tr>::value_type ArrayHandleIterator<Tr>::operator*() const
404 {
405   return Tr::to_cpp_type(*pos_);
406 }
407 
408 template <class Tr>
409 inline typename ArrayHandleIterator<Tr>::value_type ArrayHandleIterator<Tr>::operator[](
410   difference_type offset) const
411 {
412   return Tr::to_cpp_type(pos_[offset]);
413 }
414 
415 template <class Tr>
416 inline ArrayHandleIterator<Tr>& ArrayHandleIterator<Tr>::operator++()
417 {
418   ++pos_;
419   return *this;
420 }
421 
422 template <class Tr>
423 inline const ArrayHandleIterator<Tr> ArrayHandleIterator<Tr>::operator++(int)
424 {
425   return ArrayHandleIterator<Tr>(pos_++);
426 }
427 
428 template <class Tr>
429 inline ArrayHandleIterator<Tr>& ArrayHandleIterator<Tr>::operator--()
430 {
431   --pos_;
432   return *this;
433 }
434 
435 template <class Tr>
436 inline const ArrayHandleIterator<Tr> ArrayHandleIterator<Tr>::operator--(int)
437 {
438   return ArrayHandleIterator<Tr>(pos_--);
439 }
440 
441 template <class Tr>
442 inline ArrayHandleIterator<Tr>&
443 ArrayHandleIterator<Tr>::operator+=(typename ArrayHandleIterator<Tr>::difference_type rhs)
444 {
445   pos_ += rhs;
446   return *this;
447 }
448 
449 template <class Tr>
450 inline ArrayHandleIterator<Tr>&
451 ArrayHandleIterator<Tr>::operator-=(typename ArrayHandleIterator<Tr>::difference_type rhs)
452 {
453   pos_ -= rhs;
454   return *this;
455 }
456 
457 template <class Tr>
458 inline const ArrayHandleIterator<Tr>
459 ArrayHandleIterator<Tr>::operator+(typename ArrayHandleIterator<Tr>::difference_type rhs) const
460 {
461   return ArrayHandleIterator<Tr>(pos_ + rhs);
462 }
463 
464 template <class Tr>
465 inline const ArrayHandleIterator<Tr>
466 ArrayHandleIterator<Tr>::operator-(typename ArrayHandleIterator<Tr>::difference_type rhs) const
467 {
468   return ArrayHandleIterator<Tr>(pos_ - rhs);
469 }
470 
471 template <class Tr>
472 inline typename ArrayHandleIterator<Tr>::difference_type
473 ArrayHandleIterator<Tr>::operator-(const ArrayHandleIterator<Tr>& rhs) const
474 {
475   return (pos_ - rhs.pos_);
476 }
477 
478 template <class Tr>
479 inline bool
480 ArrayHandleIterator<Tr>::operator==(const ArrayHandleIterator<Tr>& rhs) const
481 {
482   return (pos_ == rhs.pos_);
483 }
484 
485 template <class Tr>
486 inline bool
487 ArrayHandleIterator<Tr>::operator!=(const ArrayHandleIterator<Tr>& rhs) const
488 {
489   return (pos_ != rhs.pos_);
490 }
491 
492 template <class Tr>
493 inline bool
494 ArrayHandleIterator<Tr>::operator<(const ArrayHandleIterator<Tr>& rhs) const
495 {
496   return (pos_ < rhs.pos_);
497 }
498 
499 template <class Tr>
500 inline bool
501 ArrayHandleIterator<Tr>::operator>(const ArrayHandleIterator<Tr>& rhs) const
502 {
503   return (pos_ > rhs.pos_);
504 }
505 
506 template <class Tr>
507 inline bool
508 ArrayHandleIterator<Tr>::operator<=(const ArrayHandleIterator<Tr>& rhs) const
509 {
510   return (pos_ <= rhs.pos_);
511 }
512 
513 template <class Tr>
514 inline bool
515 ArrayHandleIterator<Tr>::operator>=(const ArrayHandleIterator<Tr>& rhs) const
516 {
517   return (pos_ >= rhs.pos_);
518 }
519 
520 } // namespace Container_Helpers
521 
522 /**** Glib::ArrayHandle<> **************************************************/
523 
524 template <class T, class Tr>
525 template <class Cont>
526 inline ArrayHandle<T, Tr>::ArrayHandle(const Cont& container)
527 : size_(Glib::Container_Helpers::ArraySourceTraits<Tr, Cont>::get_size(container)),
528   parray_(Glib::Container_Helpers::ArraySourceTraits<Tr, Cont>::get_data(container, size_)),
529   ownership_(Glib::Container_Helpers::ArraySourceTraits<Tr, Cont>::initial_ownership)
530 {
531 }
532 
533 template <class T, class Tr>
534 inline ArrayHandle<T, Tr>::ArrayHandle(const typename ArrayHandle<T, Tr>::CType* array,
535   std::size_t array_size, Glib::OwnershipType ownership)
536 : size_((array) ? array_size : 0), parray_(array), ownership_(ownership)
537 {
538 }
539 
540 template <class T, class Tr>
541 inline ArrayHandle<T, Tr>::ArrayHandle(
542   const typename ArrayHandle<T, Tr>::CType* array, Glib::OwnershipType ownership)
543 : size_((array) ? Glib::Container_Helpers::compute_array_size(array) : 0),
544   parray_(array),
545   ownership_(ownership)
546 {
547 }
548 
549 template <class T, class Tr>
550 inline ArrayHandle<T, Tr>::ArrayHandle(const ArrayHandle<T, Tr>& other)
551 : size_(other.size_), parray_(other.parray_), ownership_(other.ownership_)
552 {
553   other.ownership_ = Glib::OWNERSHIP_NONE;
554 }
555 
556 template <class T, class Tr>
557 ArrayHandle<T, Tr>::~ArrayHandle() noexcept
558 {
559   if (parray_ && ownership_ != Glib::OWNERSHIP_NONE)
560   {
561     if (ownership_ != Glib::OWNERSHIP_SHALLOW)
562     {
563       // Deep ownership: release each container element.
564       const CType* const pend = parray_ + size_;
565       for (const CType* p = parray_; p != pend; ++p)
566         Tr::release_c_type(*p);
567     }
568     g_free(const_cast<CType*>(parray_));
569   }
570 }
571 
572 template <class T, class Tr>
573 inline typename ArrayHandle<T, Tr>::const_iterator
574 ArrayHandle<T, Tr>::begin() const
575 {
576   return Glib::Container_Helpers::ArrayHandleIterator<Tr>(parray_);
577 }
578 
579 template <class T, class Tr>
580 inline typename ArrayHandle<T, Tr>::const_iterator
581 ArrayHandle<T, Tr>::end() const
582 {
583   return Glib::Container_Helpers::ArrayHandleIterator<Tr>(parray_ + size_);
584 }
585 
586 template <class T, class Tr>
587 template <class U>
588 inline ArrayHandle<T, Tr>::operator std::vector<U>() const
589 {
590 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
591   return std::vector<U>(this->begin(), this->end());
592 #else
593   std::vector<U> temp;
594   temp.reserve(this->size());
595   Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
596   return temp;
597 #endif
598 }
599 
600 template <class T, class Tr>
601 template <class U>
602 inline ArrayHandle<T, Tr>::operator std::deque<U>() const
603 {
604 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
605   return std::deque<U>(this->begin(), this->end());
606 #else
607   std::deque<U> temp;
608   Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
609   return temp;
610 #endif
611 }
612 
613 template <class T, class Tr>
614 template <class U>
615 inline ArrayHandle<T, Tr>::operator std::list<U>() const
616 {
617 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
618   return std::list<U>(this->begin(), this->end());
619 #else
620   std::list<U> temp;
621   Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
622   return temp;
623 #endif
624 }
625 
626 template <class T, class Tr>
627 template <class Cont>
628 inline void
629 ArrayHandle<T, Tr>::assign_to(Cont& container) const
630 {
631 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
632   container.assign(this->begin(), this->end());
633 #else
634   Cont temp;
635   Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
636   container.swap(temp);
637 #endif
638 }
639 
640 template <class T, class Tr>
641 template <class Out>
642 inline void
643 ArrayHandle<T, Tr>::copy(Out pdest) const
644 {
645   std::copy(this->begin(), this->end(), pdest);
646 }
647 
648 template <class T, class Tr>
649 inline const typename ArrayHandle<T, Tr>::CType*
650 ArrayHandle<T, Tr>::data() const
651 {
652   return parray_;
653 }
654 
655 template <class T, class Tr>
656 inline std::size_t
657 ArrayHandle<T, Tr>::size() const
658 {
659   return size_;
660 }
661 
662 template <class T, class Tr>
663 inline bool
664 ArrayHandle<T, Tr>::empty() const
665 {
666   return (size_ == 0);
667 }
668 
669 /**** Glib::ArrayHandle<bool> **********************************************/
670 
671 template <class Cont>
672 inline ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::ArrayHandle(const Cont& container)
673 : size_(Glib::Container_Helpers::BoolArraySourceTraits<Cont>::get_size(container)),
674   parray_(Glib::Container_Helpers::BoolArraySourceTraits<Cont>::get_data(container, size_)),
675   ownership_(Glib::Container_Helpers::BoolArraySourceTraits<Cont>::initial_ownership)
676 {
677 }
678 
679 inline ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::ArrayHandle(
680   const gboolean* array, std::size_t array_size, Glib::OwnershipType ownership)
681 : size_((array) ? array_size : 0), parray_(array), ownership_(ownership)
682 {
683 }
684 
685 inline ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::ArrayHandle(
686   const gboolean* array, Glib::OwnershipType ownership)
687 : size_((array) ? Glib::Container_Helpers::compute_array_size(array) : 0),
688   parray_(array),
689   ownership_(ownership)
690 {
691 }
692 
693 inline ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::ArrayHandle(
694   const ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>& other)
695 : size_(other.size_), parray_(other.parray_), ownership_(other.ownership_)
696 {
697   other.ownership_ = Glib::OWNERSHIP_NONE;
698 }
699 
700 inline ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::const_iterator
701 ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::begin() const
702 {
703   return Glib::Container_Helpers::ArrayHandleIterator<Tr>(parray_);
704 }
705 
706 inline ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::const_iterator
707 ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::end() const
708 {
709   return Glib::Container_Helpers::ArrayHandleIterator<Tr>(parray_ + size_);
710 }
711 
712 template <class Cont>
713 inline void
714 ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::assign_to(Cont& container) const
715 {
716 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
717   container.assign(this->begin(), this->end());
718 #else
719   Cont temp;
720   Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
721   container.swap(temp);
722 #endif
723 }
724 
725 template <class Out>
726 inline void
727 ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::copy(Out pdest) const
728 {
729   std::copy(this->begin(), this->end(), pdest);
730 }
731 
732 inline const gboolean*
733 ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::data() const
734 {
735   return parray_;
736 }
737 
738 inline std::size_t
739 ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::size() const
740 {
741   return size_;
742 }
743 
744 inline bool
745 ArrayHandle<bool, Container_Helpers::TypeTraits<bool>>::empty() const
746 {
747   return (size_ == 0);
748 }
749 
750 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
751 
752 } // namespace Glib
753 
754 #endif /* _GLIBMM_ARRAYHANDLE_H */
755