LeechCraft  0.6.70-13729-g7046a9d2a7
Modular cross-platform feature rich live environment.
functor.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  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #pragma once
31 
32 #include <functional>
33 #include <optional>
34 #include <boost/optional.hpp>
35 #include "typeclassutil.h"
36 #include "void.h"
37 
38 namespace LC
39 {
40 namespace Util
41 {
55  template<typename T>
57  {
58  using UndefinedTag = void;
59 
70  template<typename F>
71  using FmapResult_t = detail::ImplementationType;
72 
87  template<typename F>
88  static FmapResult_t<F> Apply (const T& functor, const F& function);
89  };
90 
91  namespace detail
92  {
93  template<typename T>
94  constexpr bool IsFunctorImpl (int, typename InstanceFunctor<T>::UndefinedTag* = nullptr)
95  {
96  return false;
97  }
98 
99  template<typename T>
100  constexpr bool IsFunctorImpl (float)
101  {
102  return true;
103  }
104  }
105 
112  template<typename T>
113  constexpr bool IsFunctor ()
114  {
115  return detail::IsFunctorImpl<T> (0);
116  }
117 
125  template<typename T, typename F>
127 
148  template<typename T, typename F, typename = std::enable_if_t<IsFunctor<T> ()>>
149  FmapResult_t<T, F> Fmap (const T& functor, const F& function)
150  {
151  return InstanceFunctor<T>::Apply (functor, function);
152  }
153 
174  template<typename T, typename F>
175  auto operator* (const F& function, const T& functor) -> decltype (Fmap (functor, function))
176  {
177  return Fmap (functor, function);
178  }
179 
200  template<typename T, typename F>
201  auto operator* (const T& functor, const F& function) -> decltype (Fmap (functor, function))
202  {
203  return Fmap (functor, function);
204  }
205 
206  namespace detail
207  {
208  template<typename T>
210  {
211  using Type = T;
212  };
213 
214  template<>
215  struct WrapVoidResult<void>
216  {
217  using Type = Void;
218  };
219 
220  template<typename T>
222  }
223 
234  template<typename T>
235  struct InstanceFunctor<boost::optional<T>>
236  {
237  template<typename F>
238  using FmapResult_t = boost::optional<detail::WrapVoidResult_t<std::decay_t<std::result_of_t<F (T)>>>>;
239 
240  template<typename F>
241  static FmapResult_t<F> Apply (const boost::optional<T>& t, const F& f)
242  {
243  if (!t)
244  return {};
245 
246  if constexpr (std::is_same_v<FmapResult_t<F>, boost::optional<Void>>)
247  {
248  std::invoke (f, *t);
249  return { Void {} };
250  }
251  else
252  return { std::invoke (f, *t) };
253  }
254  };
255 
256  template<typename T>
257  struct InstanceFunctor<std::optional<T>>
258  {
259  template<typename F>
260  using FmapResult_t = std::optional<detail::WrapVoidResult_t<std::decay_t<std::result_of_t<F (T)>>>>;
261 
262  template<typename F>
263  static FmapResult_t<F> Apply (const std::optional<T>& t, const F& f)
264  {
265  if (!t)
266  return {};
267 
268  if constexpr (std::is_same_v<FmapResult_t<F>, std::optional<Void>>)
269  {
270  std::invoke (f, *t);
271  return { Void {} };
272  }
273  else
274  return { std::invoke (f, *t) };
275  }
276  };
277 }
278 }
static FmapResult_t< F > Apply(const std::optional< T > &t, const F &f)
Definition: functor.h:263
Definition: prelude.h:38
static FmapResult_t< F > Apply(const T &functor, const F &function)
Applies the function to the each of the elements inside the functor.
constexpr bool IsFunctorImpl(int, typename InstanceFunctor< T >::UndefinedTag *=nullptr)
Definition: functor.h:94
detail::ImplementationType FmapResult_t
The type of the functor after its elements were mapped by the function F.
Definition: functor.h:71
STL namespace.
typename InstanceFunctor< T >::template FmapResult_t< F > FmapResult_t
The result type of the contents of the functor T mapped by function F.
Definition: functor.h:126
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:955
FmapResult_t< T, F > Fmap(const T &functor, const F &function)
Apply the function f to the elements in functor.
Definition: functor.h:149
The Functor class is used for types that can be mapped over.
Definition: functor.h:56
static FmapResult_t< F > Apply(const boost::optional< T > &t, const F &f)
Definition: functor.h:241
auto operator*(const AF &af, const AV &av) -> decltype(GSL(af, av))
Definition: applicative.h:64
constexpr bool IsFunctor()
Checks whether the given type has a Functor instance for it.
Definition: functor.h:113
typename WrapVoidResult< T >::Type WrapVoidResult_t
Definition: functor.h:221
std::optional< detail::WrapVoidResult_t< std::decay_t< std::result_of_t< F(T)> >> > FmapResult_t
Definition: functor.h:260
Definition: constants.h:35
boost::optional< detail::WrapVoidResult_t< std::decay_t< std::result_of_t< F(T)> >> > FmapResult_t
Definition: functor.h:238
A proper void type, akin to unit (or ()) type in functional languages.
Definition: void.h:41