New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
traits.hpp in vendors/XIOS/current/extern/boost/include/boost/numeric/ublas – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/numeric/ublas/traits.hpp @ 3408

Last change on this file since 3408 was 3408, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

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