DGtal  1.2.0
FunctorHolder.h
1 
17 #pragma once
18 
29 #if defined(FunctorHolder_RECURSES)
30 #error Recursive header files inclusion detected in FunctorHolder.h
31 #else // defined(FunctorHolder_RECURSES)
33 #define FunctorHolder_RECURSES
34 
35 #if !defined FunctorHolder_h
37 #define FunctorHolder_h
38 
40 // Inclusions
41 #include <iostream>
42 #include <type_traits>
43 #include <functional>
44 #include <memory>
46 
47 namespace DGtal
48 {
49 namespace functors
50 {
51 
53 // Implementation details
54 namespace
55 {
56 
58  template <bool>
59  struct Invoker
60  {
61  template <typename F, typename... T>
62  static inline
63  auto apply(F && fn, T &&... args)
64  -> decltype((std::forward<F>(fn))(std::forward<T>(args)...))
65  {
66  return (std::forward<F>(fn))(std::forward<T>(args)...);
67  }
68  };
69 
71  template <>
72  struct Invoker<true>
73  {
74  template <typename F, typename... T>
75  static inline
76  auto apply(F && fn, T &&... args)
77  -> decltype((*std::forward<F>(fn))(std::forward<T>(args)...))
78  {
79  return (*std::forward<F>(fn))(std::forward<T>(args)...);
80  }
81  };
82 
84  struct SharedPtrTrait
85  {
86  template <typename T>
87  static constexpr std::true_type apply(std::shared_ptr<T> const&) { return {}; }
88 
89  template <typename T>
90  static constexpr std::false_type apply(T const&) { return {}; }
91  };
92 
94  struct ReferenceWrapperTrait
95  {
96  template <typename T>
97  static constexpr std::true_type apply(std::reference_wrapper<T> const&) { return {}; }
98 
99  template <typename T>
100  static constexpr std::false_type apply(T const&) { return {}; }
101  };
102 
103 } // anonymous namespace
104 
105 
107 // class FunctorHolder
148 template <
149  typename FunctorStorage,
150  bool NeedDereference
151 >
153 {
154  // ------------------------- Private Datas --------------------------------
155 private:
156 
157  FunctorStorage myFunctor;
158 
159  // ----------------------- Standard services ------------------------------
160 public:
161 
167  template <
168  typename Function,
169  // SFINAE trick to disable this constructor in a copy/move construction context.
170  typename std::enable_if<!std::is_base_of<FunctorHolder, typename std::decay<Function>::type>::value, int>::type = 0
171  >
172  explicit FunctorHolder(Function && fn)
173  : myFunctor(std::forward<Function>(fn))
174  {
175  }
176 
177  // ----------------------- Interface --------------------------------------
178 public:
179 
185  template <typename... T>
186  inline auto operator() (T &&... args) const
187  -> decltype(Invoker<NeedDereference>::apply(this->myFunctor, std::forward<T>(args)...))
188  {
189  return Invoker<NeedDereference>::apply(myFunctor, std::forward<T>(args)...);
190  }
191 
197  template <typename... T>
198  inline auto operator() (T &&... args)
199  -> decltype(Invoker<NeedDereference>::apply(this->myFunctor, std::forward<T>(args)...))
200  {
201  return Invoker<NeedDereference>::apply(myFunctor, std::forward<T>(args)...);
202  }
203 
208  inline
209  void selfDisplay ( std::ostream & out ) const
210  {
211  out << "[FunctorHolder]";
212  if ( SharedPtrTrait::apply(myFunctor) )
213  out << " using std::shared_ptr storage (rvalue)";
214  else if ( ReferenceWrapperTrait::apply(myFunctor) )
215  out << " using std::reference_wrapper storage (lvalue)";
216  else
217  out << " using custom storage";
218  }
219 
224  inline constexpr
225  bool isValid() const
226  {
227  return true;
228  }
229 }; // End of class FunctorHolder
230 
237 template <typename FunctorStorage, bool NeedDereference>
238 std::ostream&
239 operator<< ( std::ostream & out, const FunctorHolder<FunctorStorage, NeedDereference> & object )
240 {
241  object.selfDisplay( out );
242  return out;
243 }
244 
246 // Implementation details
247 namespace {
248 
250  template <typename Function>
251  inline auto holdFunctorImpl(Function && fn, std::true_type)
252  -> FunctorHolder<decltype(std::ref(std::forward<Function>(fn))), false>
253  {
254  return FunctorHolder<decltype(std::ref(std::forward<Function>(fn))), false>{ std::forward<Function>(fn) };
255  }
256 
258  template <typename Function>
259  inline auto holdFunctorImpl(Function && fn, std::false_type)
260  -> FunctorHolder<std::shared_ptr<Function>, true>
261  {
262  return FunctorHolder<std::shared_ptr<Function>, true>{ std::make_shared<Function>(std::forward<Function>(fn)) };
263  }
264 
265 } // anonymous namespace
266 
267 
269 // FunctorHolder construction helper
278 template <typename Function>
279 inline auto holdFunctor(Function && fn)
280  -> decltype(holdFunctorImpl(std::forward<Function>(fn), typename std::is_lvalue_reference<Function>{})) // Can we please pass to C++14 ?
281 {
282  return holdFunctorImpl(std::forward<Function>(fn), typename std::is_lvalue_reference<Function>{});
283 }
284 
285 } // namespace functors
286 } // namespace DGtal
287 
288 #endif // !defined FunctorHolder_h
289 
290 #undef FunctorHolder_RECURSES
291 #endif // else defined(FunctorHolder_RECURSES)
Aim: hold any callable object (function, functor, lambda, ...) as a C(Unary)Functor model.
FunctorHolder(Function &&fn)
Constructor.
void selfDisplay(std::ostream &out) const
Writes/Displays the object on an output stream.
constexpr bool isValid() const
Checks the validity/consistency of the object.
auto operator()(T &&... args) const -> decltype(Invoker< NeedDereference >::apply(this->myFunctor, std::forward< T >(args)...))
Invokes the stored callable object in a constant context.
FunctorStorage myFunctor
The callable object.
std::ostream & operator<<(std::ostream &out, const FunctorHolder< FunctorStorage, NeedDereference > &object)
Overloads 'operator<<' for displaying objects of class FunctorHolder.
auto holdFunctor(Function &&fn) -> decltype(holdFunctorImpl(std::forward< Function >(fn), typename std::is_lvalue_reference< Function >{}))
Hold any callable object (function, functor, lambda, ...) as a C(Unary)Functor model.
DGtal is the top-level namespace which contains all DGtal functions and types.