yat  0.8.3pre
iterator_traits.h
00001 #ifndef _theplu_yat_utility_iterator_traits_
00002 #define _theplu_yat_utility_iterator_traits_
00003 
00004 // $Id: iterator_traits.h 2472 2011-04-12 20:58:28Z peter $
00005 
00006 /*
00007   Copyright (C) 2007 Jari Häkkinen, Peter Johansson
00008   Copyright (C) 2008 Jari Häkkinen, Peter Johansson, Markus Ringnér
00009   Copyright (C) 2010, 2011 Peter Johansson
00010 
00011   This file is part of the yat library, http://dev.thep.lu.se/yat
00012 
00013   The yat library is free software; you can redistribute it and/or
00014   modify it under the terms of the GNU General Public License as
00015   published by the Free Software Foundation; either version 3 of the
00016   License, or (at your option) any later version.
00017 
00018   The yat library is distributed in the hope that it will be useful,
00019   but WITHOUT ANY WARRANTY; without even the implied warranty of
00020   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00021   General Public License for more details.
00022 
00023   You should have received a copy of the GNU General Public License
00024   along with yat. If not, see <http://www.gnu.org/licenses/>.
00025 */
00026 
00027 #include "DataWeight.h"
00028 
00029 #include <boost/mpl/logical.hpp>
00030 #include <boost/type_traits/is_const.hpp>
00031 #include <boost/type_traits/is_convertible.hpp>
00032 #include <boost/type_traits/is_same.hpp>
00033 #include <boost/type_traits/remove_reference.hpp>
00034 #include <boost/utility/enable_if.hpp>
00035 
00036 #include <iterator>
00037 
00038 namespace theplu {
00039 namespace yat {
00040 namespace utility {
00041 
00046   struct unweighted_iterator_tag {};
00047     
00054   struct weighted_iterator_tag {};
00055 
00056 
00057 namespace detail {
00063   template <typename T, typename Enable = void>
00064   struct weighted_iterator_traits_detail {
00068     typedef unweighted_iterator_tag type;
00069   };  
00070 
00076   template <typename T>
00077   struct weighted_iterator_traits_detail<T, typename boost::enable_if<typename boost::is_convertible<T, DataWeight> >::type > {
00081     typedef weighted_iterator_tag type;
00082   };  
00083 
00084 } // namespace detail
00085 
00086 
00094   template <class Iterator>
00095   struct weighted_iterator_traits 
00096   {
00097   private:
00098     typedef typename std::iterator_traits<Iterator>::value_type value;
00099   public:
00104     typedef typename detail::weighted_iterator_traits_detail<value>::type type;
00105   };
00106 
00107 
00108 namespace detail {
00116   template <class T1, class T2>
00117   struct unweighted_type_and {
00121     typedef weighted_iterator_tag type;
00122   };
00123 
00130   template <>
00131   struct unweighted_type_and<unweighted_iterator_tag, unweighted_iterator_tag> {
00135     typedef unweighted_iterator_tag type;
00136   };
00137 } // namespace detail
00138 
00144   template <class T1, class T2>
00145   struct weighted_if_any2 {
00146   private:
00147     typedef typename weighted_iterator_traits<T1>::type w_type1;
00148     typedef typename weighted_iterator_traits<T2>::type w_type2;
00149   public:
00151     typedef typename detail::unweighted_type_and<w_type1, w_type2>::type type;
00152   };
00153 
00157   template <class T1, class T2, class T3>
00158   struct weighted_if_any3 {
00159   private:
00160     typedef typename weighted_if_any2<T1, T2>::type tmp;
00161     typedef typename weighted_iterator_traits<T3>::type w_type3;
00162   public:
00164     typedef typename detail::unweighted_type_and<tmp, w_type3>::type type;
00165   };
00166 
00167   namespace detail {
00173     inline void 
00174     check_iterator_is_unweighted(utility::unweighted_iterator_tag x){} 
00175   } // namespace detail
00176 
00182   template <class Iter>
00183   void check_iterator_is_unweighted(Iter iter) 
00184   { detail::check_iterator_is_unweighted(typename 
00185                                  weighted_iterator_traits<Iter>::type());
00186   }
00187 
00188 
00189 namespace detail {
00190 
00200   typedef char yes;
00207   typedef char (&no)[2];
00216   yes has_mutable(double&);
00224   template<typename T>
00225   no has_mutable(const T&);
00226 
00234   template <class Iter>
00235   struct iter_has_mutable_data
00236   {
00238     static Iter iter;
00240     static const bool value = 
00241       sizeof(has_mutable((*iter).data())) == sizeof(yes);
00242   };
00243 
00244 
00252   template <class Iter>
00253   struct iter_has_mutable_weight
00254   {
00256     static Iter iter;
00258     static const bool value = 
00259       sizeof(has_mutable((*iter).weight())) == sizeof(yes);
00260   };
00261 
00262 
00274   template<typename Iter>
00275   struct is_weighted 
00276     : public boost::is_same<weighted_iterator_tag
00277                             , typename weighted_iterator_traits<Iter>::type> 
00278   {};
00279 
00285   template<typename Iter>
00286   struct is_unweighted 
00287     : public boost::is_same<unweighted_iterator_tag
00288                             , typename weighted_iterator_traits<Iter>::type> 
00289   {};
00290 
00291 
00299   template <typename Iter, typename Enable = void>
00300   struct iterator_traits_detail {
00304     typedef typename std::iterator_traits<Iter>::reference data_reference;
00305 
00309     typedef const double weight_reference;
00310 
00314     data_reference data(Iter iter) const { return *iter; }
00315 
00319     weight_reference weight(Iter iter) const { return 1.0; }
00320   };
00321 
00326   template<bool>
00327   struct mutable_reference {
00329     typedef const double type;
00330   };
00331 
00336   template<>
00337   struct mutable_reference<true> {
00339     typedef double& type;
00340   };
00341 
00342 
00348   // we need remove_reference because is_const seems to not work on const&
00349   template <typename Iter>
00350   struct iterator_traits_detail<Iter, 
00351                          typename boost::enable_if<is_weighted<Iter> >::type >
00352   {
00357     typedef 
00358     typename mutable_reference<iter_has_mutable_data<Iter>::value>::type 
00359     data_reference;
00360 
00365     typedef 
00366     typename mutable_reference<iter_has_mutable_weight<Iter>::value>::type 
00367     weight_reference;
00368 
00372     data_reference data(Iter iter) const { return (*iter).data(); }
00373 
00377     weight_reference weight(Iter iter) const { return (*iter).weight(); }
00378   };
00379 
00380 } // namespace detail
00381 
00390   template <typename Iter>
00391   struct iterator_traits {
00392   private:
00393     typedef detail::iterator_traits_detail<Iter> traits;
00394   public:
00404     typedef typename traits::data_reference data_reference;
00405 
00414     typedef typename traits::weight_reference weight_reference;
00415 
00419     data_reference data(Iter iter) const 
00420     { return traits().data(iter); }
00421 
00425     weight_reference weight(Iter iter) const 
00426     { return traits().weight(iter); }
00427 
00428   };
00429 
00430 }}} // of namespace utility, yat, and theplu
00431 
00432 #endif

Generated on Thu Dec 20 2012 03:12:58 for yat by  doxygen 1.8.0-20120409