- Main Page
- Related Pages
- Classes
- Files

- File List

# traits.hpp

    00001 //
    00002 //  Copyright (c) 2000-2002
    00003 //  Joerg Walter, Mathias Koch
    00004 //
    00005 //  Distributed under the Boost Software License, Version 1.0. (See
    00006 //  accompanying file LICENSE_1_0.txt or copy at
    00007 //  http://www.boost.org/LICENSE_1_0.txt)
    00008 //
    00009 //  The authors gratefully acknowledge the support of
    00010 //  GeNeSys mbH & Co. KG in producing this work.
    00011 //
    00012
    00013 #ifndef _BOOST_UBLAS_TRAITS_
    00014 #define _BOOST_UBLAS_TRAITS_
    00015
    00016 #include <iterator>
    00017 #include <complex>
    00018 #include <boost/config/no_tr1/cmath.hpp>
    00019
    00020 #include <boost/numeric/ublas/detail/config.hpp>
    00021 #include <boost/numeric/ublas/detail/iterator.hpp>
    00022 #include <boost/numeric/ublas/detail/returntype_deduction.hpp>
    00023
    00024 #include <boost/type_traits.hpp>
    00025 #include <complex>
    00026 #include <boost/typeof/typeof.hpp>
    00027 #include <boost/utility/enable_if.hpp>
    00028 #include <boost/type_traits/is_float.hpp>
    00029 #include <boost/type_traits/is_integral.hpp>
    00030 #include <boost/mpl/and.hpp>
    00031
    00032 // anonymous namespace to avoid ADL issues
    00033 namespace {
    00034   template<class T> T boost_numeric_ublas_sqrt (const T& t) {
    00035     using namespace std;
    00036     // we'll find either std::sqrt or else another version via ADL:
    00037     return sqrt (t);
    00038   }
    00039   template<class T> T boost_numeric_ublas_abs (const T& t) {
    00040     using namespace std;
    00041     // we'll find either std::abs or else another version via ADL:
    00042     return abs (t);
    00043   }
    00044 }
    00045
    00046 namespace boost { namespace numeric { namespace ublas {
    00047
    00048     // Use Joel de Guzman's return type deduction
    00049     // uBLAS assumes a common return type for all binary arithmetic operators
    00050     template<class X, class Y>
    00051     struct promote_traits {
    00052         typedef type_deduction_detail::base_result_of<X, Y> base_type;
    00053         static typename base_type::x_type x;
    00054         static typename base_type::y_type y;
    00055         static const std::size_t size = sizeof (
    00056                 type_deduction_detail::test<
    00057                     typename base_type::x_type
    00058                   , typename base_type::y_type
    00059                 >(x + y)     // Use x+y to stand of all the arithmetic actions
    00060             );
    00061
    00062         static const std::size_t index = (size / sizeof (char)) - 1;
    00063         typedef typename mpl::at_c<
    00064             typename base_type::types, index>::type id;
    00065         typedef typename id::type promote_type;
    00066     };
    00067
    00068       template<typename R, typename I>
    00069       typename boost::enable_if<
    00070         mpl::and_<
    00071           boost::is_float<R>,
    00072           boost::is_integral<I>
    00073           >,
    00074         std::complex<R> >::type inline operator+ (I in1, std::complex<R> const& in2 ) {
    00075         return R (in1) + in2;
    00076       }
    00077
    00078       template<typename R, typename I>
    00079       typename boost::enable_if<
    00080         mpl::and_<
    00081           boost::is_float<R>,
    00082           boost::is_integral<I>
    00083           >,
    00084         std::complex<R> >::type inline operator+ (std::complex<R> const& in1, I in2) {
    00085         return in1 + R (in2);
    00086       }
    00087
    00088       template<typename R, typename I>
    00089       typename boost::enable_if<
    00090         mpl::and_<
    00091           boost::is_float<R>,
    00092           boost::is_integral<I>
    00093           >,
    00094         std::complex<R> >::type inline operator- (I in1, std::complex<R> const& in2) {
    00095         return R (in1) - in2;
    00096       }
    00097
    00098       template<typename R, typename I>
    00099       typename boost::enable_if<
    00100         mpl::and_<
    00101           boost::is_float<R>,
    00102           boost::is_integral<I>
    00103           >,
    00104         std::complex<R> >::type inline operator- (std::complex<R> const& in1, I in2) {
    00105         return in1 - R (in2);
    00106       }
    00107
    00108       template<typename R, typename I>
    00109       typename boost::enable_if<
    00110         mpl::and_<
    00111           boost::is_float<R>,
    00112           boost::is_integral<I>
    00113           >,
    00114         std::complex<R> >::type inline operator* (I in1, std::complex<R> const& in2) {
    00115         return R (in1) * in2;
    00116       }
    00117
    00118       template<typename R, typename I>
    00119       typename boost::enable_if<
    00120         mpl::and_<
    00121           boost::is_float<R>,
    00122           boost::is_integral<I>
    00123           >,
    00124         std::complex<R> >::type inline operator* (std::complex<R> const& in1, I in2) {
    00125         return in1 * R(in2);
    00126       }
    00127
    00128       template<typename R, typename I>
    00129       typename boost::enable_if<
    00130         mpl::and_<
    00131           boost::is_float<R>,
    00132           boost::is_integral<I>
    00133           >,
    00134         std::complex<R> >::type inline operator/ (I in1, std::complex<R> const& in2) {
    00135         return R(in1) / in2;
    00136       }
    00137
    00138       template<typename R, typename I>
    00139       typename boost::enable_if<
    00140         mpl::and_<
    00141           boost::is_float<R>,
    00142           boost::is_integral<I>
    00143           >,
    00144         std::complex<R> >::type inline operator/ (std::complex<R> const& in1, I in2) {
    00145         return in1 / R (in2);
    00146       }
    00147
    00148
    00149
    00150     // Type traits - generic numeric properties and functions
    00151     template<class T>
    00152     struct type_traits;
    00153
    00154     // Define properties for a generic scalar type
    00155     template<class T>
    00156     struct scalar_traits {
    00157         typedef scalar_traits<T> self_type;
    00158         typedef T value_type;
    00159         typedef const T &const_reference;
    00160         typedef T &reference;
    00161
    00162         typedef T real_type;
    00163         typedef real_type precision_type;       // we do not know what type has more precision then the real_type
    00164
    00165         static const unsigned plus_complexity = 1;
    00166         static const unsigned multiplies_complexity = 1;
    00167
    00168         static
    00169         BOOST_UBLAS_INLINE
    00170         real_type real (const_reference t) {
    00171                 return t;
    00172         }
    00173         static
    00174         BOOST_UBLAS_INLINE
    00175         real_type imag (const_reference /*t*/) {
    00176                 return 0;
    00177         }
    00178         static
    00179         BOOST_UBLAS_INLINE
    00180         value_type conj (const_reference t) {
    00181                 return t;
    00182         }
    00183
    00184         static
    00185         BOOST_UBLAS_INLINE
    00186         real_type type_abs (const_reference t) {
    00187             return boost_numeric_ublas_abs (t);
    00188         }
    00189         static
    00190         BOOST_UBLAS_INLINE
    00191         value_type type_sqrt (const_reference t) {
    00192             // force a type conversion back to value_type for intgral types
    00193             return value_type (boost_numeric_ublas_sqrt (t));
    00194         }
    00195
    00196         static
    00197         BOOST_UBLAS_INLINE
    00198         real_type norm_1 (const_reference t) {
    00199             return self_type::type_abs (t);
    00200         }
    00201         static
    00202         BOOST_UBLAS_INLINE
    00203         real_type norm_2 (const_reference t) {
    00204             return self_type::type_abs (t);
    00205         }
    00206         static
    00207         BOOST_UBLAS_INLINE
    00208         real_type norm_inf (const_reference t) {
    00209             return self_type::type_abs (t);
    00210         }
    00211
    00212         static
    00213         BOOST_UBLAS_INLINE
    00214         bool equals (const_reference t1, const_reference t2) {
    00215             return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
    00216                    (std::max) ((std::max) (self_type::norm_inf (t1),
    00217                                        self_type::norm_inf (t2)),
    00218                              BOOST_UBLAS_TYPE_CHECK_MIN);
    00219         }
    00220     };
    00221
    00222     // Define default type traits, assume T is a scalar type
    00223     template<class T>
    00224     struct type_traits : scalar_traits <T> {
    00225         typedef type_traits<T> self_type;
    00226         typedef T value_type;
    00227         typedef const T &const_reference;
    00228         typedef T &reference;
    00229
    00230         typedef T real_type;
    00231         typedef real_type precision_type;
    00232         static const unsigned multiplies_complexity = 1;
    00233
    00234     };
    00235
    00236     // Define real type traits
    00237     template<>
    00238     struct type_traits<float> : scalar_traits<float> {
    00239         typedef type_traits<float> self_type;
    00240         typedef float value_type;
    00241         typedef const value_type &const_reference;
    00242         typedef value_type &reference;
    00243         typedef value_type real_type;
    00244         typedef double precision_type;
    00245     };
    00246     template<>
    00247     struct type_traits<double> : scalar_traits<double> {
    00248         typedef type_traits<double> self_type;
    00249         typedef double value_type;
    00250         typedef const value_type &const_reference;
    00251         typedef value_type &reference;
    00252         typedef value_type real_type;
    00253         typedef long double precision_type;
    00254     };
    00255     template<>
    00256     struct type_traits<long double>  : scalar_traits<long double> {
    00257         typedef type_traits<long double> self_type;
    00258         typedef long double value_type;
    00259         typedef const value_type &const_reference;
    00260         typedef value_type &reference;
    00261         typedef value_type real_type;
    00262         typedef value_type precision_type;
    00263     };
    00264
    00265     // Define properties for a generic complex type
    00266     template<class T>
    00267     struct complex_traits {
    00268         typedef complex_traits<T> self_type;
    00269         typedef T value_type;
    00270         typedef const T &const_reference;
    00271         typedef T &reference;
    00272
    00273         typedef typename T::value_type real_type;
    00274         typedef real_type precision_type;       // we do not know what type has more precision then the real_type
    00275
    00276         static const unsigned plus_complexity = 2;
    00277         static const unsigned multiplies_complexity = 6;
    00278
    00279         static
    00280         BOOST_UBLAS_INLINE
    00281         real_type real (const_reference t) {
    00282                 return std::real (t);
    00283         }
    00284         static
    00285         BOOST_UBLAS_INLINE
    00286         real_type imag (const_reference t) {
    00287                 return std::imag (t);
    00288         }
    00289         static
    00290         BOOST_UBLAS_INLINE
    00291         value_type conj (const_reference t) {
    00292                 return std::conj (t);
    00293         }
    00294
    00295         static
    00296         BOOST_UBLAS_INLINE
    00297         real_type type_abs (const_reference t) {
    00298                 return abs (t);
    00299         }
    00300         static
    00301         BOOST_UBLAS_INLINE
    00302         value_type type_sqrt (const_reference t) {
    00303                 return sqrt (t);
    00304         }
    00305
    00306         static
    00307         BOOST_UBLAS_INLINE
    00308         real_type norm_1 (const_reference t) {
    00309             return self_type::type_abs (t);
    00310             // original computation has been replaced because a complex number should behave like a scalar type
    00311             // return type_traits<real_type>::type_abs (self_type::real (t)) +
    00312             //       type_traits<real_type>::type_abs (self_type::imag (t));
    00313         }
    00314         static
    00315         BOOST_UBLAS_INLINE
    00316         real_type norm_2 (const_reference t) {
    00317             return self_type::type_abs (t);
    00318         }
    00319         static
    00320         BOOST_UBLAS_INLINE
    00321         real_type norm_inf (const_reference t) {
    00322             return self_type::type_abs (t);
    00323             // original computation has been replaced because a complex number should behave like a scalar type
    00324             // return (std::max) (type_traits<real_type>::type_abs (self_type::real (t)),
    00325             //                 type_traits<real_type>::type_abs (self_type::imag (t)));
    00326         }
    00327
    00328         static
    00329         BOOST_UBLAS_INLINE
    00330         bool equals (const_reference t1, const_reference t2) {
    00331             return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
    00332                    (std::max) ((std::max) (self_type::norm_inf (t1),
    00333                                        self_type::norm_inf (t2)),
    00334                              BOOST_UBLAS_TYPE_CHECK_MIN);
    00335         }
    00336     };
    00337
    00338     // Define complex type traits
    00339     template<>
    00340     struct type_traits<std::complex<float> > : complex_traits<std::complex<float> >{
    00341         typedef type_traits<std::complex<float> > self_type;
    00342         typedef std::complex<float> value_type;
    00343         typedef const value_type &const_reference;
    00344         typedef value_type &reference;
    00345         typedef float real_type;
    00346         typedef std::complex<double> precision_type;
    00347
    00348     };
    00349     template<>
    00350     struct type_traits<std::complex<double> > : complex_traits<std::complex<double> >{
    00351         typedef type_traits<std::complex<double> > self_type;
    00352         typedef std::complex<double> value_type;
    00353         typedef const value_type &const_reference;
    00354         typedef value_type &reference;
    00355         typedef double real_type;
    00356         typedef std::complex<long double> precision_type;
    00357     };
    00358     template<>
    00359     struct type_traits<std::complex<long double> > : complex_traits<std::complex<long double> > {
    00360         typedef type_traits<std::complex<long double> > self_type;
    00361         typedef std::complex<long double> value_type;
    00362         typedef const value_type &const_reference;
    00363         typedef value_type &reference;
    00364         typedef long double real_type;
    00365         typedef value_type precision_type;
    00366     };
    00367
    00368 #ifdef BOOST_UBLAS_USE_INTERVAL
    00369     // Define scalar interval type traits
    00370     template<>
    00371     struct type_traits<boost::numeric::interval<float> > : scalar_traits<boost::numeric::interval<float> > {
    00372         typedef type_traits<boost::numeric::interval<float> > self_type;
    00373         typedef boost::numeric::interval<float> value_type;
    00374         typedef const value_type &const_reference;
    00375         typedef value_type &reference;
    00376         typedef value_type real_type;
    00377         typedef boost::numeric::interval<double> precision_type;
    00378
    00379     };
    00380     template<>
    00381     struct type_traits<boost::numeric::interval<double> > : scalar_traits<boost::numeric::interval<double> > {
    00382         typedef type_traits<boost::numeric::interval<double> > self_type;
    00383         typedef boost::numeric::interval<double> value_type;
    00384         typedef const value_type &const_reference;
    00385         typedef value_type &reference;
    00386         typedef value_type real_type;
    00387         typedef boost::numeric::interval<long double> precision_type;
    00388     };
    00389     template<>
    00390     struct type_traits<boost::numeric::interval<long double> > : scalar_traits<boost::numeric::interval<long double> > {
    00391         typedef type_traits<boost::numeric::interval<long double> > self_type;
    00392         typedef boost::numeric::interval<long double> value_type;
    00393         typedef const value_type &const_reference;
    00394         typedef value_type &reference;
    00395         typedef value_type real_type;
    00396         typedef value_type precision_type;
    00397     };
    00398 #endif
    00399
    00400
    00401     // Storage tags -- hierarchical definition of storage characteristics
    00402
    00403     struct unknown_storage_tag {};
    00404     struct sparse_proxy_tag: public unknown_storage_tag {};
    00405     struct sparse_tag: public sparse_proxy_tag {};
    00406     struct packed_proxy_tag: public sparse_proxy_tag {};
    00407     struct packed_tag: public packed_proxy_tag {};
    00408     struct dense_proxy_tag: public packed_proxy_tag {};
    00409     struct dense_tag: public dense_proxy_tag {};
    00410
    00411     template<class S1, class S2>
    00412     struct storage_restrict_traits {
    00413         typedef S1 storage_category;
    00414     };
    00415
    00416     template<>
    00417     struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
    00418         typedef sparse_proxy_tag storage_category;
    00419     };
    00420     template<>
    00421     struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
    00422         typedef sparse_proxy_tag storage_category;
    00423     };
    00424     template<>
    00425     struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
    00426         typedef sparse_proxy_tag storage_category;
    00427     };
    00428
    00429     template<>
    00430     struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
    00431         typedef packed_proxy_tag storage_category;
    00432     };
    00433     template<>
    00434     struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
    00435         typedef packed_proxy_tag storage_category;
    00436     };
    00437     template<>
    00438     struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
    00439         typedef sparse_proxy_tag storage_category;
    00440     };
    00441
    00442     template<>
    00443     struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
    00444         typedef sparse_proxy_tag storage_category;
    00445     };
    00446
    00447     template<>
    00448     struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
    00449         typedef dense_proxy_tag storage_category;
    00450     };
    00451     template<>
    00452     struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
    00453         typedef packed_proxy_tag storage_category;
    00454     };
    00455     template<>
    00456     struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
    00457         typedef sparse_proxy_tag storage_category;
    00458     };
    00459
    00460     template<>
    00461     struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
    00462         typedef packed_proxy_tag storage_category;
    00463     };
    00464     template<>
    00465     struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
    00466         typedef sparse_proxy_tag storage_category;
    00467     };
    00468
    00469
    00470     // Iterator tags -- hierarchical definition of storage characteristics
    00471
    00472     struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
    00473     struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
    00474     struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};
    00475
    00476     // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-)
    00477     template<class IC>
    00478     struct iterator_base_traits {};
    00479
    00480     template<>
    00481     struct iterator_base_traits<std::forward_iterator_tag> {
    00482         template<class I, class T>
    00483         struct iterator_base {
    00484             typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
    00485         };
    00486     };
    00487
    00488     template<>
    00489     struct iterator_base_traits<std::bidirectional_iterator_tag> {
    00490         template<class I, class T>
    00491         struct iterator_base {
    00492             typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
    00493         };
    00494     };
    00495     template<>
    00496     struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
    00497         template<class I, class T>
    00498         struct iterator_base {
    00499             typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
    00500         };
    00501     };
    00502
    00503     template<>
    00504     struct iterator_base_traits<std::random_access_iterator_tag> {
    00505         template<class I, class T>
    00506         struct iterator_base {
    00507             typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
    00508         };
    00509     };
    00510     template<>
    00511     struct iterator_base_traits<packed_random_access_iterator_tag> {
    00512         template<class I, class T>
    00513         struct iterator_base {
    00514             typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
    00515         };
    00516     };
    00517     template<>
    00518     struct iterator_base_traits<dense_random_access_iterator_tag> {
    00519         template<class I, class T>
    00520         struct iterator_base {
    00521             typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
    00522         };
    00523     };
    00524
    00525     template<class I1, class I2>
    00526     struct iterator_restrict_traits {
    00527         typedef I1 iterator_category;
    00528     };
    00529
    00530     template<>
    00531     struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
    00532         typedef sparse_bidirectional_iterator_tag iterator_category;
    00533     };
    00534     template<>
    00535     struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
    00536         typedef sparse_bidirectional_iterator_tag iterator_category;
    00537     };
    00538
    00539     template<>
    00540     struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
    00541         typedef sparse_bidirectional_iterator_tag iterator_category;
    00542     };
    00543     template<>
    00544     struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
    00545         typedef sparse_bidirectional_iterator_tag iterator_category;
    00546     };
    00547
    00548     template<>
    00549     struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
    00550         typedef packed_random_access_iterator_tag iterator_category;
    00551     };
    00552     template<>
    00553     struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
    00554         typedef packed_random_access_iterator_tag iterator_category;
    00555     };
    00556
    00557     template<class I>
    00558     BOOST_UBLAS_INLINE
    00559     void increment (I &it, const I &it_end, typename I::difference_type compare, packed_random_access_iterator_tag) {
    00560         it += (std::min) (compare, it_end - it);
    00561     }
    00562     template<class I>
    00563     BOOST_UBLAS_INLINE
    00564     void increment (I &it, const I &/* it_end */, typename I::difference_type /* compare */, sparse_bidirectional_iterator_tag) {
    00565         ++ it;
    00566     }
    00567     template<class I>
    00568     BOOST_UBLAS_INLINE
    00569     void increment (I &it, const I &it_end, typename I::difference_type compare) {
    00570         increment (it, it_end, compare, typename I::iterator_category ());
    00571     }
    00572
    00573     template<class I>
    00574     BOOST_UBLAS_INLINE
    00575     void increment (I &it, const I &it_end) {
    00576 #if BOOST_UBLAS_TYPE_CHECK
    00577         I cit (it);
    00578         while (cit != it_end) {
    00579             BOOST_UBLAS_CHECK (*cit == typename I::value_type/*zero*/(), internal_logic ());
    00580             ++ cit;
    00581         }
    00582 #endif
    00583         it = it_end;
    00584     }
    00585
    00586     namespace detail {
    00587
    00588         // specialisation which define whether a type has a trivial constructor
    00589         // or not. This is used by array types.
    00590         template<typename T>
    00591         struct has_trivial_constructor : public boost::has_trivial_constructor<T> {};
    00592
    00593         template<typename T>
    00594         struct has_trivial_destructor : public boost::has_trivial_destructor<T> {};
    00595
    00596         template<typename FLT>
    00597         struct has_trivial_constructor<std::complex<FLT> > : public boost::true_type {};
    00598
    00599         template<typename FLT>
    00600         struct has_trivial_destructor<std::complex<FLT> > : public boost::true_type {};
    00601
    00602     }
    00603
    00604
    00608     template < class E >
    00609     struct container_view_traits {
    00611         typedef typename E::size_type             size_type;
    00613         typedef typename E::difference_type       difference_type;
    00614
    00616         typedef typename E::storage_category      storage_category;
    00617
    00619         typedef typename E::value_type            value_type;
    00621         typedef typename E::const_reference       const_reference;
    00622
    00624         typedef typename E::const_closure_type    const_closure_type;
    00625     };
    00626
    00630     template < class E >
    00631     struct mutable_container_traits {
    00633         typedef typename E::reference             reference;
    00634
    00636         typedef typename E::closure_type          closure_type;
    00637     };
    00638
    00642     template < class E >
    00643     struct container_traits
    00644         : container_view_traits<E>, mutable_container_traits<E> {
    00645
    00646     };
    00647
    00648
    00652     template < class MATRIX >
    00653     struct matrix_view_traits : container_view_traits <MATRIX> {
    00654
    00656         typedef typename MATRIX::orientation_category  orientation_category;
    00657
    00659         typedef typename MATRIX::const_iterator1  const_iterator1;
    00660
    00662         typedef typename MATRIX::const_iterator2  const_iterator2;
    00663     };
    00664
    00668     template < class MATRIX >
    00669     struct mutable_matrix_traits
    00670         : mutable_container_traits <MATRIX> {
    00671
    00673         typedef typename MATRIX::iterator1  iterator1;
    00674
    00676         typedef typename MATRIX::iterator2  iterator2;
    00677     };
    00678
    00679
    00683     template < class MATRIX >
    00684     struct matrix_traits
    00685         : matrix_view_traits <MATRIX>, mutable_matrix_traits <MATRIX> {
    00686     };
    00687
    00691     template < class VECTOR >
    00692     struct vector_view_traits : container_view_traits <VECTOR> {
    00693
    00695         typedef typename VECTOR::const_iterator  const_iterator;
    00696
    00698         static
    00699         const_iterator begin(const VECTOR & v) {
    00700             return v.begin();
    00701         }
    00703         static
    00704         const_iterator end(const VECTOR & v) {
    00705             return v.end();
    00706         }
    00707
    00708     };
    00709
    00713     template < class VECTOR >
    00714     struct mutable_vector_traits : mutable_container_traits <VECTOR> {
    00716         typedef typename VECTOR::iterator  iterator;
    00717
    00719         static
    00720         iterator begin(VECTOR & v) {
    00721             return v.begin();
    00722         }
    00723
    00725         static
    00726         iterator end(VECTOR & v) {
    00727             return v.end();
    00728         }
    00729     };
    00730
    00734     template < class VECTOR >
    00735     struct vector_traits
    00736         : vector_view_traits <VECTOR>, mutable_vector_traits <VECTOR> {
    00737     };
    00738
    00739
    00740     // Note: specializations for T[N] and T[M][N] have been moved to traits/c_array.hpp
    00741
    00742 }}}
    00743
    00744 #endif