DGtal 1.3.0
Loading...
Searching...
No Matches
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
47namespace DGtal
48{
49namespace functors
50{
51
53// Implementation details
54namespace
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
148template <
149 typename FunctorStorage,
150 bool NeedDereference
151>
153{
154 // ------------------------- Private Datas --------------------------------
155private:
156
157 FunctorStorage myFunctor;
158
159 // ----------------------- Standard services ------------------------------
160public:
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 --------------------------------------
178public:
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
237template <typename FunctorStorage, bool NeedDereference>
238std::ostream&
239operator<< ( std::ostream & out, const FunctorHolder<FunctorStorage, NeedDereference> & object )
240{
241 object.selfDisplay( out );
242 return out;
243}
244
246// Implementation details
247namespace {
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
278template <typename Function>
279inline 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.
STL namespace.