LeechCraft  0.6.70-15082-g543737046d
Modular cross-platform feature rich live environment.
monadplus.h
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Distributed under the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7  **********************************************************************/
8 
9 #pragma once
10 
11 #include <numeric>
12 #include <optional>
13 
14 namespace LC
15 {
16 namespace Util
17 {
18  template<typename T, typename SFINAE = void>
19  struct InstanceMonadPlus
20  {
21  using UndefinedTag = void;
22  };
23 
24  namespace detail
25  {
26  template<typename T>
27  constexpr bool IsMonadPlusImpl (int, typename InstanceMonadPlus<T>::UndefinedTag* = nullptr)
28  {
29  return false;
30  }
31 
32  template<typename T>
33  constexpr bool IsMonadPlusImpl (float)
34  {
35  return true;
36  }
37  }
38 
39  template<typename T>
40  constexpr bool IsMonadPlus ()
41  {
42  return detail::IsMonadPlusImpl<T> (0);
43  }
44 
45  template<typename MP>
46  MP Mzero ()
47  {
49  }
50 
51  const struct
52  {
53  template<typename MP>
54  auto operator() (const MP& m1) const
55  {
56  return [m1] (const MP& m2) { return InstanceMonadPlus<MP>::Mplus (m1, m2); };
57  }
58  } Mplus {};
59 
60  template<typename MP>
61  auto operator+ (const MP& m1, const MP& m2) -> decltype (Mplus (m1) (m2))
62  {
63  return Mplus (m1) (m2);
64  }
65 
66  const struct
67  {
68  template<typename Vec>
69  auto operator() (Vec&& vec) const
70  {
71  using std::begin;
72  using std::end;
73  using MP = typename Vec::value_type;
74  return std::accumulate (begin (vec), end (vec), Mzero<MP> (), &operator+<MP>);
75  }
76 
77  template<typename T>
78  auto operator() (std::initializer_list<T> vec) const
79  {
80  using std::begin;
81  using std::end;
82  return std::accumulate (begin (vec), end (vec), Mzero<T> (), &operator+<T>);
83  }
84  } Msum {};
85 
86  template<typename T>
87  struct InstanceMonadPlus<std::optional<T>>
88  {
89  static std::optional<T> Mzero ()
90  {
91  return {};
92  }
93 
94  static std::optional<T> Mplus (const std::optional<T>& t1, const std::optional<T>& t2)
95  {
96  return t1 ? t1 : t2;
97  }
98  };
99 }
100 }
LC::Util::detail::IsMonadPlusImpl
constexpr bool IsMonadPlusImpl(int, typename InstanceMonadPlus< T >::UndefinedTag *=nullptr)
Definition: monadplus.h:39
LC::Util::IsMonadPlus
constexpr bool IsMonadPlus()
Definition: monadplus.h:52
LC::Util::InstanceMonadPlus::UndefinedTag
void UndefinedTag
Definition: monadplus.h:39
LC::Util::Mplus
const struct LC::Util::@1 Mplus
LC::Util::Msum
const struct LC::Util::@2 Msum
LC
Definition: constants.h:14
LC::Util::operator+
auto operator+(const MP &m1, const MP &m2) -> decltype(Mplus(m1)(m2))
Definition: monadplus.h:73
LC::Util::Mzero
MP Mzero()
Definition: monadplus.h:58