yat
0.8.3pre
|
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