LeechCraft  0.6.70-15082-g543737046d
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  * 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 <functional>
12 #include <optional>
13 #include "typeclassutil.h"
14 #include "void.h"
15 #include "either.h"
16 
17 namespace LC
18 {
19 namespace Util
20 {
34  template<typename T>
35  struct InstanceFunctor
36  {
37  using UndefinedTag = void;
38 
49  template<typename F>
50  using FmapResult_t = detail::ImplementationType;
51 
66  template<typename F>
67  static FmapResult_t<F> Apply (const T& functor, const F& function);
68  };
69 
70  namespace detail
71  {
72  template<typename T>
73  constexpr bool IsFunctorImpl (int, typename InstanceFunctor<T>::UndefinedTag* = nullptr)
74  {
75  return false;
76  }
77 
78  template<typename T>
79  constexpr bool IsFunctorImpl (float)
80  {
81  return true;
82  }
83  }
84 
91  template<typename T>
92  constexpr bool IsFunctor ()
93  {
94  return detail::IsFunctorImpl<T> (0);
95  }
96 
104  template<typename T, typename F>
106 
127  template<typename T, typename F, typename = std::enable_if_t<IsFunctor<T> ()>>
128  FmapResult_t<T, F> Fmap (const T& functor, const F& function)
129  {
130  return InstanceFunctor<T>::Apply (functor, function);
131  }
132 
153  template<typename T, typename F>
154  auto operator* (const F& function, const T& functor) -> decltype (Fmap (functor, function))
155  {
156  return Fmap (functor, function);
157  }
158 
179  template<typename T, typename F>
180  auto operator* (const T& functor, const F& function) -> decltype (Fmap (functor, function))
181  {
182  return Fmap (functor, function);
183  }
184 
185  namespace detail
186  {
187  template<typename T>
188  struct WrapVoidResult
189  {
190  using Type = T;
191  };
192 
193  template<>
194  struct WrapVoidResult<void>
195  {
196  using Type = Void;
197  };
198 
199  template<typename T>
201  }
202 
213  template<typename T>
214  struct InstanceFunctor<std::optional<T>>
215  {
216  template<typename F>
217  using FmapResult_t = std::optional<detail::WrapVoidResult_t<std::decay_t<std::result_of_t<F (T)>>>>;
218 
219  template<typename F>
220  static FmapResult_t<F> Apply (const std::optional<T>& t, const F& f)
221  {
222  if (!t)
223  return {};
224 
225  if constexpr (std::is_same_v<FmapResult_t<F>, std::optional<Void>>)
226  {
227  std::invoke (f, *t);
228  return { Void {} };
229  }
230  else
231  return { std::invoke (f, *t) };
232  }
233  };
234 
235  template<typename L, typename R>
236  struct InstanceFunctor<Either<L, R>>
237  {
238  template<typename F>
239  using FmapResult_t = Either<L, std::result_of_t<F (R)>>;
240 
241  template<typename F>
242  static FmapResult_t<F> Apply (const Either<L, R>& either, const F& f)
243  {
244  if (either.IsLeft ())
245  return FmapResult_t<F>::Left (either.GetLeft ());
246 
247  return FmapResult_t<F>::Right (f (either.GetRight ()));
248  }
249  };
250 }
251 }
LC::Util::InstanceFunctor::FmapResult_t
detail::ImplementationType FmapResult_t
The type of the functor after its elements were mapped by the function F.
Definition: functor.h:68
LC::Util::InstanceFunctor::Apply
static FmapResult_t< F > Apply(const T &functor, const F &function)
Applies the function to the each of the elements inside the functor.
void.h
LC::Util::FmapResult_t
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:117
LC::Util::detail::IsFunctorImpl
constexpr bool IsFunctorImpl(int, typename InstanceFunctor< T >::UndefinedTag *=nullptr)
Definition: functor.h:85
typeclassutil.h
either.h
LC::Util::Fmap
FmapResult_t< T, F > Fmap(const T &functor, const F &function)
Apply the function f to the elements in functor.
Definition: functor.h:140
LC::Util::operator*
auto operator*(const AF &af, const AV &av) -> decltype(GSL(af, av))
Definition: applicative.h:55
LC::Util::InstanceFunctor
The Functor class is used for types that can be mapped over.
Definition: functor.h:47
LC::Util::detail::WrapVoidResult_t
typename WrapVoidResult< T >::Type WrapVoidResult_t
Definition: functor.h:212
LC::Util::IsFunctor
constexpr bool IsFunctor()
Checks whether the given type has a Functor instance for it.
Definition: functor.h:104
LC
Definition: constants.h:14
LC::Util::oral::sph::f
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:952
LC::Util::Void
A proper void type, akin to unit (or ()) type in functional languages.
Definition: void.h:32
LC::Util::InstanceFunctor::UndefinedTag
void UndefinedTag
Definition: functor.h:55
LC::Util::detail::WrapVoidResult::Type
T Type
Definition: functor.h:202