DGtal  1.0.0
testFunctorHolder.cpp
1 
27 #include <functional>
29 
30 #include "DGtal/base/FunctorHolder.h"
31 #include "DGtal/base/Common.h"
32 #include "DGtal/base/CUnaryFunctor.h"
33 
34 #include "DGtalCatch.h"
36 
37 using namespace DGtal;
38 using namespace DGtal::functors;
39 using namespace std;
40 
42 // Functor and functions
43 
44 struct Functor
45 {
46  double cst;
47 
48  explicit Functor(double c) : cst(c) {}
49  inline double operator() (double v) const { return v + cst; }
50 };
51 
52 double add(double v)
53 {
54  return v + 1.5;
55 }
56 
57 
59 // Test cases
60 
61 TEST_CASE( "Holding a lambda", "[lambda]" )
62 {
63  double cst = 1.5;
64 
65  // Holding an unary lambda by mutable lvalue
66  {
67  auto fn = [&cst] (double v) { return v + cst; };
68  auto holder = holdFunctor(fn);
69  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
70  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
71  REQUIRE( holder(0.5) == 2.0 );
72  auto holder2 = holder;
73  REQUIRE( holder2(0.5) == 2.0 );
74  }
75 
76  // Holding an unary lambda by constant lvalue
77  {
78  const auto fn = [&cst] (double v) { return v + cst; };
79  auto holder = holdFunctor(fn);
80  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
81  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
82  REQUIRE( holder(0.5) == 2.0 );
83  auto holder2 = holder;
84  REQUIRE( holder2(0.5) == 2.0 );
85  }
86 
87  // Holding an unary lambda by rvalue
88  {
89  auto holder = holdFunctor( [&cst] (double v) { return v + cst; } );
90  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
91  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
92  REQUIRE( holder(0.5) == 2.0 );
93  auto holder2 = holder;
94  REQUIRE( holder2(0.5) == 2.0 );
95  }
96 
97  // Holding an unary mutable lambda by rvalue
98  {
99  auto holder = holdFunctor( [cst] (double v) mutable { return v + cst; } );
100  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
101  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
102  REQUIRE( holder(0.5) == 2.0 );
103  auto holder2 = holder;
104  REQUIRE( holder2(0.5) == 2.0 );
105  }
106 
107  // Holding a binary lambda by rvalue
108  {
109  auto holder = holdFunctor( [] (double v, double c) { return v + c; } );
110  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
111  REQUIRE( holder(0.5, 1.5) == 2.0 );
112  auto holder2 = holder;
113  REQUIRE( holder2(0.5, 1.5) == 2.0 );
114  }
115 }
116 
117 TEST_CASE( "Holding a functor", "[functor]" )
118 {
119  double cst = 1.5;
120 
121  // Holding an unary functor by mutable lvalue
122  {
123  auto fn = Functor(cst);
124  auto holder = holdFunctor(fn);
125  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
126  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
127  REQUIRE( holder(0.5) == 2.0 );
128  auto holder2 = holder;
129  REQUIRE( holder2(0.5) == 2.0 );
130  }
131 
132  // Holding an unary functor by constant lvalue
133  {
134  const auto fn = Functor(cst);
135  auto holder = holdFunctor(fn);
136  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
137  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
138  REQUIRE( holder(0.5) == 2.0 );
139  auto holder2 = holder;
140  REQUIRE( holder2(0.5) == 2.0 );
141  }
142 
143  // Holding an unary functor by rvalue
144  {
145  auto holder = holdFunctor( Functor(cst) );
146  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
147  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
148  REQUIRE( holder(0.5) == 2.0 );
149  auto holder2 = holder;
150  REQUIRE( holder2(0.5) == 2.0 );
151  }
152 }
153 
154 TEST_CASE( "Holding a function", "[function]" )
155 {
156  // Holding a function by reference
157  {
158  auto holder = holdFunctor( add );
159  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
160  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
161  REQUIRE( holder(0.5) == 2.0 );
162  auto holder2 = holder;
163  REQUIRE( holder2(0.5) == 2.0 );
164  }
165 
166  // Holding a function by address
167  {
168  auto holder = holdFunctor( &add );
169  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
170  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
171  REQUIRE( holder(0.5) == 2.0 );
172  auto holder2 = holder;
173  REQUIRE( holder2(0.5) == 2.0 );
174  }
175 }
176 
177 TEST_CASE( "Holding a std::function", "[std::function]" )
178 {
179  double cst = 1.5;
180 
181  // Holding a std::function
182  std::function<double(double)> fn = Functor(cst);
183  auto holder = holdFunctor( fn );
184  BOOST_CONCEPT_ASSERT(( boost::Assignable<decltype(holder)> ));
185  BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor<decltype(holder), double, double> ));
186  REQUIRE( holder(0.5) == 2.0 );
187  auto holder2 = holder;
188  REQUIRE( holder2(0.5) == 2.0 );
189 }
InHalfPlaneBySimple3x3Matrix< Point, double > Functor
Go to http://www.sgi.com/tech/stl/Assignable.html.
Definition: Boost.dox:32
functors namespace gathers all DGtal functors.
Aim: Defines a unary functor, which associates arguments to results.
Definition: CUnaryFunctor.h:89
REQUIRE(domain.isInside(aPoint))
ch add(Point(102.2, 50.2))
TEST_CASE("int container traits", "[int][traits]")
DGtal is the top-level namespace which contains all DGtal functions and types.
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.