SigUtil  0.95
Utility modules for modern C++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
maybe.hpp
Go to the documentation of this file.
1 /*
2 Copyright© 2014 Akihiro Nishimura
3 
4 This software is released under the MIT License.
5 http://opensource.org/licenses/mit-license.php
6 */
7 
8 #ifndef _SIG_UTIL_MAYBE_HPP
9 #define _SIG_UTIL_MAYBE_HPP
10 
11 #include "../sigutil.hpp"
12 #include "eval.hpp"
13 #include "type_convert.hpp"
14 #include "container_traits.hpp"
15 
16 #if SIG_ENABLE_BOOST && SIG_USE_OPTIONAL
17 #include <boost/optional.hpp>
18 #endif
19 
21 
40 namespace sig
41 {
42 
43 // Maybe(boost.optional)の有効・無効に関係なくコードを統一的に記述するための処理
44 #if SIG_ENABLE_BOOST && SIG_USE_OPTIONAL
45  template <class T> using Maybe = boost::optional<T>;
46 
48 
54  template <class T, class R = typename sig::impl::remove_const_reference<T>::type>
55  Maybe<R> Just(T&& v){ return Maybe<R>(std::forward<T>(v)); }
56 
57  template <class T>
58  Maybe<T> Just(T const& v){ return Maybe<T>(v); } // T is given explicitly
59 
61 
66  template <class T = void>
68  {
69  return boost::none;
70  }
71 
73 
80  template <class T> auto Nothing(T const& dummy)-> Maybe<T>{ return boost::none; }
81 
82 
84  template <class T> bool isJust(Maybe<T> const& m){ return static_cast<bool>(m); }
85  constexpr bool isJust(boost::none_t m){ return false; }
86 
87 
89  template <class T> bool isNothing(Maybe<T> const& m){ return !static_cast<bool>(m); }
90  constexpr bool isNothing(boost::none_t m){ return true; }
91 
92 
94 
113  template <class T> T& fromJust(Maybe<T>& m){ return *m; }
114  template <class T> T const& fromJust(Maybe<T> const& m){ return *m; }
115  template <class T> T&& fromJust(Maybe<T>&& m){ return std::move(*m); }
116 
117 
119 
130  template <class T> T& operator*(Maybe<T>& m){ return *m; }
131  template <class T> T const& operator*(Maybe<T> const& m){ return *m; }
132  template <class T> T&& operator*(Maybe<T>&& m){ return *std::move(m); }
133 
134 
136 
145  template <class T> T& fromMaybe(T& def, Maybe<T>& m){ return m ? *m : def; }
146  template <class T> T const& fromMaybe(T const& def, Maybe<T> const& m){ return m ? *m : def; }
147  template <class T> T&& fromMaybe(T&& def, Maybe<T>&& m){ return m ? std::move(*m) : std::move(def); }
148  template <class T> T&& fromMaybe(T&& def, boost::none_t m){ return std::move(def); }
149 
150 
152 
168  template <class F, class C> auto mapMaybe(F const& f, C const& list)
169  ->typename impl::container_traits<C>::template rebind<
170  typename std::remove_reference<decltype(*(impl::eval(
171  f,
172  std::declval<typename impl::container_traits<C>::value_type>()
173  )))>::type
174  >
175  {
176  using R = typename impl::container_traits<C>::template rebind<typename std::remove_reference<decltype(*(impl::eval(f, std::declval<typename impl::container_traits<C>::value_type>())))>::type>;
177 
178  R result;
179 
180  for (auto const& e : list){
181  auto r = f(e);
182  if (r) impl::container_traits<R>::add_element(result, *r);
183  }
184 
185  return result;
186  }
187 
188 
190 
211  template <class T, class F>
212  auto operator>>=(Maybe<T> const& m, F const& f) ->decltype(impl::eval(f, std::declval<T>()))
213  {
214  if (m) return f(*m);
215  else return boost::none;
216  }
217 
219 
240  template <class F, class T>
241  auto operator<<=(F const& f, Maybe<T> const& m) ->decltype(impl::eval(f, std::declval<T>()))
242  {
243  if (m) return f(*m);
244  else return boost::none;
245  }
246 
247 
249 
272  template <class T1, class T2>
273  auto operator<<=(Maybe<T1>& m, T2 const& v) ->Maybe<T1>&
274  {
275  if (m) *m = v;
276  else m = Maybe<T1>(static_cast<T1>(v));
277  return m;
278  }
279 
280 #else
281  // optionalが使えない場合の代替処理
282  // 当ライブラリコードを統一的に記述するために用いているため、ユーザコードでの使用は非推奨
283 
284  template <class I, class D = void> using Maybe = std::tuple<I, bool>;
285 
286  template <class I> Maybe<I> Just(I v){ return std::make_tuple(v, true); }
287 
288  template <class I> Maybe<I> Nothing(I&& dummy){ return std::make_tuple(dummy, false); }
289  template <class I> Maybe<I> Nothing(I const& dummy){ return std::make_tuple(dummy, false); }
290 
291  template <class I> bool isJust(Maybe<I> const& m){ return std::get<1>(m); }
292 
293  template <class I> bool isNothing(Maybe<I> const& m){ return !std::get<1>(m); }
294 
295  template <class T> T& fromJust(Maybe<T>& m){ return *m; }
296  template <class T> T const& fromJust(Maybe<T> const& m){ return *m; }
297  template <class T> T&& fromJust(Maybe<T>&& m){ return *std::move(m); }
298 
299  template <class T> T& operator*(Maybe<T>& m){
300  if (!std::get<1>(m)) std::abort();
301  return std::get<0>(m);
302  }
303  template <class T> T const& operator*(Maybe<T> const& m){
304  if (!std::get<1>(m)) std::abort();
305  return std::get<0>(m);
306  }
307  template <class T> T&& operator*(Maybe<T>&& m){
308  if (!std::get<1>(m)) std::abort();
309  return std::move(std::get<0>(m));
310  }
311 
312 
313  template <class T1, class T2>
314  auto operator<<=(Maybe<T1>& m, T2 const& v) ->Maybe<T1>&
315  {
316  std::get<0>(m) = v;
317  std::get<1>(m) = true;
318  return m;
319  }
320 
321 #endif
322 
323 
324 } // sig
325 #endif
auto operator*(T1 &&v1, T2 &&v2) -> decltype(binary_operation(mult_t(), std::forward< T1 >(v1), std::forward< T2 >(v2)))
auto mapMaybe(F const &f, C const &list) -> typename impl::container_traits< C >::template rebind< typename std::remove_reference< decltype(*(impl::eval(f, std::declval< typename impl::container_traits< C >::value_type >())))>::type >
Maybeを返す関数を指定するfilter関数.(a -> Maybe b) -> [a] -> [b].
Definition: maybe.hpp:168
auto operator>>=(Maybe< T > const &m, F const &f) -> decltype(impl::eval(f, std::declval< T >()))
Haskell風のbind演算子. Maybe m => m a -> (a -> m b) -> m b.
Definition: maybe.hpp:212
bool isNothing(Maybe< T > const &m)
Nothingであるか調べる関数.Maybe a -> Bool.
Definition: maybe.hpp:89
T & fromMaybe(T &def, Maybe< T > &m)
Maybeから値を取り出す関数.もしNothingなら引数のデフォルト値を返す.a -> Maybe a -> a...
Definition: maybe.hpp:145
auto Nothing() -> typename impl::SameIf< T, void, typename boost::none_t, Maybe< T >>::type
値コンストラクタ
Definition: maybe.hpp:67
Maybe< R > Just(T &&v)
値コンストラクタ
Definition: maybe.hpp:55
bool isJust(Maybe< T > const &m)
Justであるか調べる関数.Maybe a -> Bool.
Definition: maybe.hpp:84
boost::optional< T > Maybe
Definition: maybe.hpp:45
auto eval(F &&f, Args &&...args) -> decltype(f(std::forward< Args >(args)...))
Definition: eval.hpp:37
T & fromJust(Maybe< T > &m)
Justから値を取り出す関数.Maybe a -> a.
Definition: maybe.hpp:113
Definition: array.hpp:15