]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/numeric/ublas/include/boost/numeric/ublas/traits.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / numeric / ublas / include / boost / numeric / ublas / traits.hpp
1 //
2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // The authors gratefully acknowledge the support of
10 // GeNeSys mbH & Co. KG in producing this work.
11 //
12
13 #ifndef _BOOST_UBLAS_TRAITS_
14 #define _BOOST_UBLAS_TRAITS_
15
16 #include <iterator>
17 #include <complex>
18 #include <boost/config/no_tr1/cmath.hpp>
19
20 #include <boost/numeric/ublas/detail/config.hpp>
21 #include <boost/numeric/ublas/detail/iterator.hpp>
22 #include <boost/numeric/ublas/detail/returntype_deduction.hpp>
23 #ifdef BOOST_UBLAS_USE_INTERVAL
24 #include <boost/numeric/interval.hpp>
25 #endif
26
27 #include <boost/type_traits.hpp>
28 #include <complex>
29 #include <boost/typeof/typeof.hpp>
30 #include <boost/utility/enable_if.hpp>
31 #include <boost/type_traits/is_float.hpp>
32 #include <boost/type_traits/is_integral.hpp>
33 #include <boost/type_traits/is_unsigned.hpp>
34 #include <boost/mpl/and.hpp>
35
36 // anonymous namespace to avoid ADL issues
37 namespace {
38 template<class T> T boost_numeric_ublas_sqrt (const T& t) {
39 using namespace std;
40 // we'll find either std::sqrt or else another version via ADL:
41 return sqrt (t);
42 }
43
44 template<typename T>
45 inline typename boost::disable_if<
46 boost::is_unsigned<T>, T >::type
47 boost_numeric_ublas_abs (const T &t ) {
48 using namespace std;
49 return abs( t );
50 }
51
52 template<typename T>
53 inline typename boost::enable_if<
54 boost::is_unsigned<T>, T >::type
55 boost_numeric_ublas_abs (const T &t ) {
56 return t;
57 }
58 }
59
60 namespace boost { namespace numeric { namespace ublas {
61
62
63 template<typename R, typename I>
64 typename boost::enable_if<
65 mpl::and_<
66 boost::is_float<R>,
67 boost::is_integral<I>
68 >,
69 std::complex<R> >::type inline operator+ (I in1, std::complex<R> const& in2 ) {
70 return R (in1) + in2;
71 }
72
73 template<typename R, typename I>
74 typename boost::enable_if<
75 mpl::and_<
76 boost::is_float<R>,
77 boost::is_integral<I>
78 >,
79 std::complex<R> >::type inline operator+ (std::complex<R> const& in1, I in2) {
80 return in1 + R (in2);
81 }
82
83 template<typename R, typename I>
84 typename boost::enable_if<
85 mpl::and_<
86 boost::is_float<R>,
87 boost::is_integral<I>
88 >,
89 std::complex<R> >::type inline operator- (I in1, std::complex<R> const& in2) {
90 return R (in1) - in2;
91 }
92
93 template<typename R, typename I>
94 typename boost::enable_if<
95 mpl::and_<
96 boost::is_float<R>,
97 boost::is_integral<I>
98 >,
99 std::complex<R> >::type inline operator- (std::complex<R> const& in1, I in2) {
100 return in1 - R (in2);
101 }
102
103 template<typename R, typename I>
104 typename boost::enable_if<
105 mpl::and_<
106 boost::is_float<R>,
107 boost::is_integral<I>
108 >,
109 std::complex<R> >::type inline operator* (I in1, std::complex<R> const& in2) {
110 return R (in1) * in2;
111 }
112
113 template<typename R, typename I>
114 typename boost::enable_if<
115 mpl::and_<
116 boost::is_float<R>,
117 boost::is_integral<I>
118 >,
119 std::complex<R> >::type inline operator* (std::complex<R> const& in1, I in2) {
120 return in1 * R(in2);
121 }
122
123 template<typename R, typename I>
124 typename boost::enable_if<
125 mpl::and_<
126 boost::is_float<R>,
127 boost::is_integral<I>
128 >,
129 std::complex<R> >::type inline operator/ (I in1, std::complex<R> const& in2) {
130 return R(in1) / in2;
131 }
132
133 template<typename R, typename I>
134 typename boost::enable_if<
135 mpl::and_<
136 boost::is_float<R>,
137 boost::is_integral<I>
138 >,
139 std::complex<R> >::type inline operator/ (std::complex<R> const& in1, I in2) {
140 return in1 / R (in2);
141 }
142
143 // Use Joel de Guzman's return type deduction
144 // uBLAS assumes a common return type for all binary arithmetic operators
145 template<class X, class Y>
146 struct promote_traits {
147 typedef type_deduction_detail::base_result_of<X, Y> base_type;
148 static typename base_type::x_type x;
149 static typename base_type::y_type y;
150 static const std::size_t size = sizeof (
151 type_deduction_detail::test<
152 typename base_type::x_type
153 , typename base_type::y_type
154 >(x + y) // Use x+y to stand of all the arithmetic actions
155 );
156
157 static const std::size_t index = (size / sizeof (char)) - 1;
158 typedef typename mpl::at_c<
159 typename base_type::types, index>::type id;
160 typedef typename id::type promote_type;
161 };
162
163
164
165 // Type traits - generic numeric properties and functions
166 template<class T>
167 struct type_traits;
168
169 // Define properties for a generic scalar type
170 template<class T>
171 struct scalar_traits {
172 typedef scalar_traits<T> self_type;
173 typedef T value_type;
174 typedef const T &const_reference;
175 typedef T &reference;
176
177 typedef T real_type;
178 typedef real_type precision_type; // we do not know what type has more precision then the real_type
179
180 static const unsigned plus_complexity = 1;
181 static const unsigned multiplies_complexity = 1;
182
183 static
184 BOOST_UBLAS_INLINE
185 real_type real (const_reference t) {
186 return t;
187 }
188 static
189 BOOST_UBLAS_INLINE
190 real_type imag (const_reference /*t*/) {
191 return 0;
192 }
193 static
194 BOOST_UBLAS_INLINE
195 value_type conj (const_reference t) {
196 return t;
197 }
198
199 static
200 BOOST_UBLAS_INLINE
201 real_type type_abs (const_reference t) {
202 return boost_numeric_ublas_abs (t);
203 }
204 static
205 BOOST_UBLAS_INLINE
206 value_type type_sqrt (const_reference t) {
207 // force a type conversion back to value_type for intgral types
208 return value_type (boost_numeric_ublas_sqrt (t));
209 }
210
211 static
212 BOOST_UBLAS_INLINE
213 real_type norm_1 (const_reference t) {
214 return self_type::type_abs (t);
215 }
216 static
217 BOOST_UBLAS_INLINE
218 real_type norm_2 (const_reference t) {
219 return self_type::type_abs (t);
220 }
221 static
222 BOOST_UBLAS_INLINE
223 real_type norm_inf (const_reference t) {
224 return self_type::type_abs (t);
225 }
226
227 static
228 BOOST_UBLAS_INLINE
229 bool equals (const_reference t1, const_reference t2) {
230 return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
231 (std::max) ((std::max) (self_type::norm_inf (t1),
232 self_type::norm_inf (t2)),
233 BOOST_UBLAS_TYPE_CHECK_MIN);
234 }
235 };
236
237 // Define default type traits, assume T is a scalar type
238 template<class T>
239 struct type_traits : scalar_traits <T> {
240 typedef type_traits<T> self_type;
241 typedef T value_type;
242 typedef const T &const_reference;
243 typedef T &reference;
244
245 typedef T real_type;
246 typedef real_type precision_type;
247 static const unsigned multiplies_complexity = 1;
248
249 };
250
251 // Define real type traits
252 template<>
253 struct type_traits<float> : scalar_traits<float> {
254 typedef type_traits<float> self_type;
255 typedef float value_type;
256 typedef const value_type &const_reference;
257 typedef value_type &reference;
258 typedef value_type real_type;
259 typedef double precision_type;
260 };
261 template<>
262 struct type_traits<double> : scalar_traits<double> {
263 typedef type_traits<double> self_type;
264 typedef double value_type;
265 typedef const value_type &const_reference;
266 typedef value_type &reference;
267 typedef value_type real_type;
268 typedef long double precision_type;
269 };
270 template<>
271 struct type_traits<long double> : scalar_traits<long double> {
272 typedef type_traits<long double> self_type;
273 typedef long double value_type;
274 typedef const value_type &const_reference;
275 typedef value_type &reference;
276 typedef value_type real_type;
277 typedef value_type precision_type;
278 };
279
280 // Define properties for a generic complex type
281 template<class T>
282 struct complex_traits {
283 typedef complex_traits<T> self_type;
284 typedef T value_type;
285 typedef const T &const_reference;
286 typedef T &reference;
287
288 typedef typename T::value_type real_type;
289 typedef real_type precision_type; // we do not know what type has more precision then the real_type
290
291 static const unsigned plus_complexity = 2;
292 static const unsigned multiplies_complexity = 6;
293
294 static
295 BOOST_UBLAS_INLINE
296 real_type real (const_reference t) {
297 return std::real (t);
298 }
299 static
300 BOOST_UBLAS_INLINE
301 real_type imag (const_reference t) {
302 return std::imag (t);
303 }
304 static
305 BOOST_UBLAS_INLINE
306 value_type conj (const_reference t) {
307 return std::conj (t);
308 }
309
310 static
311 BOOST_UBLAS_INLINE
312 real_type type_abs (const_reference t) {
313 return abs (t);
314 }
315 static
316 BOOST_UBLAS_INLINE
317 value_type type_sqrt (const_reference t) {
318 return sqrt (t);
319 }
320
321 static
322 BOOST_UBLAS_INLINE
323 real_type norm_1 (const_reference t) {
324 return self_type::type_abs (t);
325 // original computation has been replaced because a complex number should behave like a scalar type
326 // return type_traits<real_type>::type_abs (self_type::real (t)) +
327 // type_traits<real_type>::type_abs (self_type::imag (t));
328 }
329 static
330 BOOST_UBLAS_INLINE
331 real_type norm_2 (const_reference t) {
332 return self_type::type_abs (t);
333 }
334 static
335 BOOST_UBLAS_INLINE
336 real_type norm_inf (const_reference t) {
337 return self_type::type_abs (t);
338 // original computation has been replaced because a complex number should behave like a scalar type
339 // return (std::max) (type_traits<real_type>::type_abs (self_type::real (t)),
340 // type_traits<real_type>::type_abs (self_type::imag (t)));
341 }
342
343 static
344 BOOST_UBLAS_INLINE
345 bool equals (const_reference t1, const_reference t2) {
346 return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
347 (std::max) ((std::max) (self_type::norm_inf (t1),
348 self_type::norm_inf (t2)),
349 BOOST_UBLAS_TYPE_CHECK_MIN);
350 }
351 };
352
353 // Define complex type traits
354 template<>
355 struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{
356 typedef type_traits<std::complex<float> > self_type;
357 typedef std::complex<float> value_type;
358 typedef const value_type &const_reference;
359 typedef value_type &reference;
360 typedef float real_type;
361 typedef std::complex<double> precision_type;
362
363 };
364 template<>
365 struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{
366 typedef type_traits<std::complex<double> > self_type;
367 typedef std::complex<double> value_type;
368 typedef const value_type &const_reference;
369 typedef value_type &reference;
370 typedef double real_type;
371 typedef std::complex<long double> precision_type;
372 };
373 template<>
374 struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > {
375 typedef type_traits<std::complex<long double> > self_type;
376 typedef std::complex<long double> value_type;
377 typedef const value_type &const_reference;
378 typedef value_type &reference;
379 typedef long double real_type;
380 typedef value_type precision_type;
381 };
382
383 #ifdef BOOST_UBLAS_USE_INTERVAL
384 // Define scalar interval type traits
385 template<>
386 struct type_traits<boost::numeric::interval<float> > : scalar_traits<boost::numeric::interval<float> > {
387 typedef type_traits<boost::numeric::interval<float> > self_type;
388 typedef boost::numeric::interval<float> value_type;
389 typedef const value_type &const_reference;
390 typedef value_type &reference;
391 typedef value_type real_type;
392 typedef boost::numeric::interval<double> precision_type;
393
394 };
395 template<>
396 struct type_traits<boost::numeric::interval<double> > : scalar_traits<boost::numeric::interval<double> > {
397 typedef type_traits<boost::numeric::interval<double> > self_type;
398 typedef boost::numeric::interval<double> value_type;
399 typedef const value_type &const_reference;
400 typedef value_type &reference;
401 typedef value_type real_type;
402 typedef boost::numeric::interval<long double> precision_type;
403 };
404 template<>
405 struct type_traits<boost::numeric::interval<long double> > : scalar_traits<boost::numeric::interval<long double> > {
406 typedef type_traits<boost::numeric::interval<long double> > self_type;
407 typedef boost::numeric::interval<long double> value_type;
408 typedef const value_type &const_reference;
409 typedef value_type &reference;
410 typedef value_type real_type;
411 typedef value_type precision_type;
412 };
413 #endif
414
415
416 // Storage tags -- hierarchical definition of storage characteristics
417
418 struct unknown_storage_tag {};
419 struct sparse_proxy_tag: public unknown_storage_tag {};
420 struct sparse_tag: public sparse_proxy_tag {};
421 struct packed_proxy_tag: public sparse_proxy_tag {};
422 struct packed_tag: public packed_proxy_tag {};
423 struct dense_proxy_tag: public packed_proxy_tag {};
424 struct dense_tag: public dense_proxy_tag {};
425
426 template<class S1, class S2>
427 struct storage_restrict_traits {
428 typedef S1 storage_category;
429 };
430
431 template<>
432 struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
433 typedef sparse_proxy_tag storage_category;
434 };
435 template<>
436 struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
437 typedef sparse_proxy_tag storage_category;
438 };
439 template<>
440 struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
441 typedef sparse_proxy_tag storage_category;
442 };
443
444 template<>
445 struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
446 typedef packed_proxy_tag storage_category;
447 };
448 template<>
449 struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
450 typedef packed_proxy_tag storage_category;
451 };
452 template<>
453 struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
454 typedef sparse_proxy_tag storage_category;
455 };
456
457 template<>
458 struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
459 typedef sparse_proxy_tag storage_category;
460 };
461
462 template<>
463 struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
464 typedef dense_proxy_tag storage_category;
465 };
466 template<>
467 struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
468 typedef packed_proxy_tag storage_category;
469 };
470 template<>
471 struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
472 typedef sparse_proxy_tag storage_category;
473 };
474
475 template<>
476 struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
477 typedef packed_proxy_tag storage_category;
478 };
479 template<>
480 struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
481 typedef sparse_proxy_tag storage_category;
482 };
483
484
485 // Iterator tags -- hierarchical definition of storage characteristics
486
487 struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
488 struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
489 struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};
490
491 // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-)
492 template<class IC>
493 struct iterator_base_traits {};
494
495 template<>
496 struct iterator_base_traits<std::forward_iterator_tag> {
497 template<class I, class T>
498 struct iterator_base {
499 typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
500 };
501 };
502
503 template<>
504 struct iterator_base_traits<std::bidirectional_iterator_tag> {
505 template<class I, class T>
506 struct iterator_base {
507 typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
508 };
509 };
510 template<>
511 struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
512 template<class I, class T>
513 struct iterator_base {
514 typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
515 };
516 };
517
518 template<>
519 struct iterator_base_traits<std::random_access_iterator_tag> {
520 template<class I, class T>
521 struct iterator_base {
522 typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
523 };
524 };
525 template<>
526 struct iterator_base_traits<packed_random_access_iterator_tag> {
527 template<class I, class T>
528 struct iterator_base {
529 typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
530 };
531 };
532 template<>
533 struct iterator_base_traits<dense_random_access_iterator_tag> {
534 template<class I, class T>
535 struct iterator_base {
536 typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
537 };
538 };
539
540 template<class I1, class I2>
541 struct iterator_restrict_traits {
542 typedef I1 iterator_category;
543 };
544
545 template<>
546 struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
547 typedef sparse_bidirectional_iterator_tag iterator_category;
548 };
549 template<>
550 struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
551 typedef sparse_bidirectional_iterator_tag iterator_category;
552 };
553
554 template<>
555 struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
556 typedef sparse_bidirectional_iterator_tag iterator_category;
557 };
558 template<>
559 struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
560 typedef sparse_bidirectional_iterator_tag iterator_category;
561 };
562
563 template<>
564 struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
565 typedef packed_random_access_iterator_tag iterator_category;
566 };
567 template<>
568 struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
569 typedef packed_random_access_iterator_tag iterator_category;
570 };
571
572 template<class I>
573 BOOST_UBLAS_INLINE
574 void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) {
575 it += (std::min) (compare, it_end - it);
576 }
577 template<class I>
578 BOOST_UBLAS_INLINE
579 void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) {
580 ++ it;
581 }
582 template<class I>
583 BOOST_UBLAS_INLINE
584 void increment (I &it, const I &it_end, typename I::difference_type compare) {
585 increment (it, it_end, compare, typename I::iterator_category ());
586 }
587
588 template<class I>
589 BOOST_UBLAS_INLINE
590 void increment (I &it, const I &it_end) {
591 #if BOOST_UBLAS_TYPE_CHECK
592 I cit (it);
593 while (cit != it_end) {
594 BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ());
595 ++ cit;
596 }
597 #endif
598 it = it_end;
599 }
600
601 namespace detail {
602
603 // specialisation which define whether a type has a trivial constructor
604 // or not. This is used by array types.
605 template<typename T>
606 struct has_trivial_constructor : public boost::has_trivial_constructor<T> {};
607
608 template<typename T>
609 struct has_trivial_destructor : public boost::has_trivial_destructor<T> {};
610
611 template<typename FLT>
612 struct has_trivial_constructor<std::complex<FLT> > : public has_trivial_constructor<FLT> {};
613
614 template<typename FLT>
615 struct has_trivial_destructor<std::complex<FLT> > : public has_trivial_destructor<FLT> {};
616
617 }
618
619
620 /** \brief Traits class to extract type information from a constant matrix or vector CONTAINER.
621 *
622 */
623 template < class E >
624 struct container_view_traits {
625 /// type of indices
626 typedef typename E::size_type size_type;
627 /// type of differences of indices
628 typedef typename E::difference_type difference_type;
629
630 /// storage category: \c unknown_storage_tag, \c dense_tag, \c packed_tag, ...
631 typedef typename E::storage_category storage_category;
632
633 /// type of elements
634 typedef typename E::value_type value_type;
635 /// const reference to an element
636 typedef typename E::const_reference const_reference;
637
638 /// type used in expressions to mark a reference to this class (usually a const container_reference<const E> or the class itself)
639 typedef typename E::const_closure_type const_closure_type;
640 };
641
642 /** \brief Traits class to extract additional type information from a mutable matrix or vector CONTAINER.
643 *
644 */
645 template < class E >
646 struct mutable_container_traits {
647 /// reference to an element
648 typedef typename E::reference reference;
649
650 /// type used in expressions to mark a reference to this class (usually a container_reference<E> or the class itself)
651 typedef typename E::closure_type closure_type;
652 };
653
654 /** \brief Traits class to extract type information from a matrix or vector CONTAINER.
655 *
656 */
657 template < class E >
658 struct container_traits
659 : container_view_traits<E>, mutable_container_traits<E> {
660
661 };
662
663
664 /** \brief Traits class to extract type information from a constant MATRIX.
665 *
666 */
667 template < class MATRIX >
668 struct matrix_view_traits : container_view_traits <MATRIX> {
669
670 /// orientation of the matrix, either \c row_major_tag, \c column_major_tag or \c unknown_orientation_tag
671 typedef typename MATRIX::orientation_category orientation_category;
672
673 /// row iterator for the matrix
674 typedef typename MATRIX::const_iterator1 const_iterator1;
675
676 /// column iterator for the matrix
677 typedef typename MATRIX::const_iterator2 const_iterator2;
678 };
679
680 /** \brief Traits class to extract additional type information from a mutable MATRIX.
681 *
682 */
683 template < class MATRIX >
684 struct mutable_matrix_traits
685 : mutable_container_traits <MATRIX> {
686
687 /// row iterator for the matrix
688 typedef typename MATRIX::iterator1 iterator1;
689
690 /// column iterator for the matrix
691 typedef typename MATRIX::iterator2 iterator2;
692 };
693
694
695 /** \brief Traits class to extract type information from a MATRIX.
696 *
697 */
698 template < class MATRIX >
699 struct matrix_traits
700 : matrix_view_traits <MATRIX>, mutable_matrix_traits <MATRIX> {
701 };
702
703 /** \brief Traits class to extract type information from a VECTOR.
704 *
705 */
706 template < class VECTOR >
707 struct vector_view_traits : container_view_traits <VECTOR> {
708
709 /// iterator for the VECTOR
710 typedef typename VECTOR::const_iterator const_iterator;
711
712 /// iterator pointing to the first element
713 static
714 const_iterator begin(const VECTOR & v) {
715 return v.begin();
716 }
717 /// iterator pointing behind the last element
718 static
719 const_iterator end(const VECTOR & v) {
720 return v.end();
721 }
722
723 };
724
725 /** \brief Traits class to extract type information from a VECTOR.
726 *
727 */
728 template < class VECTOR >
729 struct mutable_vector_traits : mutable_container_traits <VECTOR> {
730 /// iterator for the VECTOR
731 typedef typename VECTOR::iterator iterator;
732
733 /// iterator pointing to the first element
734 static
735 iterator begin(VECTOR & v) {
736 return v.begin();
737 }
738
739 /// iterator pointing behind the last element
740 static
741 iterator end(VECTOR & v) {
742 return v.end();
743 }
744 };
745
746 /** \brief Traits class to extract type information from a VECTOR.
747 *
748 */
749 template < class VECTOR >
750 struct vector_traits
751 : vector_view_traits <VECTOR>, mutable_vector_traits <VECTOR> {
752 };
753
754
755 // Note: specializations for T[N] and T[M][N] have been moved to traits/c_array.hpp
756
757 }}}
758
759 #endif