Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81418 - in trunk: boost/geometry/algorithms boost/geometry/multi/algorithms libs/geometry/test/algorithms
From: barend.gehrels_at_[hidden]
Date: 2012-11-18 14:51:01


Author: barendgehrels
Date: 2012-11-18 14:51:00 EST (Sun, 18 Nov 2012)
New Revision: 81418
URL: http://svn.boost.org/trac/boost/changeset/81418

Log:
[geometry] fixed for_each using C++11 lambda's, including adding unit test for them
Text files modified:
   trunk/boost/geometry/algorithms/for_each.hpp | 46 ++++++++++++++++--------------
   trunk/boost/geometry/multi/algorithms/for_each.hpp | 5 +--
   trunk/libs/geometry/test/algorithms/test_for_each.hpp | 60 ++++++++++++++++++++++++++++++++++++++++
   3 files changed, 87 insertions(+), 24 deletions(-)

Modified: trunk/boost/geometry/algorithms/for_each.hpp
==============================================================================
--- trunk/boost/geometry/algorithms/for_each.hpp (original)
+++ trunk/boost/geometry/algorithms/for_each.hpp 2012-11-18 14:51:00 EST (Sun, 18 Nov 2012)
@@ -44,10 +44,9 @@
 struct fe_point_per_point
 {
     template <typename Point, typename Functor>
- static inline Functor apply(Point& point, Functor f)
+ static inline void apply(Point& point, Functor& f)
     {
         f(point);
- return f;
     }
 };
 
@@ -55,11 +54,10 @@
 struct fe_point_per_segment
 {
     template <typename Point, typename Functor>
- static inline Functor apply(Point& , Functor f)
+ static inline void apply(Point& , Functor& f)
     {
         // TODO: if non-const, we should extract the points from the segment
         // and call the functor on those two points
- return f;
     }
 };
 
@@ -67,9 +65,19 @@
 struct fe_range_per_point
 {
     template <typename Range, typename Functor>
- static inline Functor apply(Range& range, Functor f)
+ static inline void apply(Range& range, Functor& f)
     {
- return (std::for_each(boost::begin(range), boost::end(range), f));
+ // The previous implementation called the std library:
+ // return (std::for_each(boost::begin(range), boost::end(range), f));
+ // But that is not accepted for capturing lambda's.
+ // It needs to do it like that to return the state of Functor f (f is passed by value in std::for_each).
+
+ // So we now loop manually.
+
+ for (typename boost::range_iterator<Range>::type it = boost::begin(range); it != boost::end(range); ++it)
+ {
+ f(*it);
+ }
     }
 };
 
@@ -77,7 +85,7 @@
 struct fe_range_per_segment
 {
     template <typename Range, typename Functor>
- static inline Functor apply(Range& range, Functor f)
+ static inline void apply(Range& range, Functor& f)
     {
         typedef typename add_const_if_c
             <
@@ -93,8 +101,6 @@
             f(s);
             previous = it++;
         }
-
- return f;
     }
 };
 
@@ -102,18 +108,16 @@
 struct fe_polygon_per_point
 {
     template <typename Polygon, typename Functor>
- static inline Functor apply(Polygon& poly, Functor f)
+ static inline void apply(Polygon& poly, Functor& f)
     {
- f = fe_range_per_point::apply(exterior_ring(poly), f);
+ fe_range_per_point::apply(exterior_ring(poly), f);
 
         typename interior_return_type<Polygon>::type rings
                     = interior_rings(poly);
         for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
         {
- f = fe_range_per_point::apply(*it, f);
+ fe_range_per_point::apply(*it, f);
         }
-
- return f;
     }
 
 };
@@ -122,18 +126,16 @@
 struct fe_polygon_per_segment
 {
     template <typename Polygon, typename Functor>
- static inline Functor apply(Polygon& poly, Functor f)
+ static inline void apply(Polygon& poly, Functor& f)
     {
- f = fe_range_per_segment::apply(exterior_ring(poly), f);
+ fe_range_per_segment::apply(exterior_ring(poly), f);
 
         typename interior_return_type<Polygon>::type rings
                     = interior_rings(poly);
         for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
         {
- f = fe_range_per_segment::apply(*it, f);
+ fe_range_per_segment::apply(*it, f);
         }
-
- return f;
     }
 
 };
@@ -235,7 +237,8 @@
 {
     concept::check<Geometry>();
 
- return dispatch::for_each_point<Geometry>::apply(geometry, f);
+ dispatch::for_each_point<Geometry>::apply(geometry, f);
+ return f;
 }
 
 
@@ -257,7 +260,8 @@
 {
     concept::check<Geometry>();
 
- return dispatch::for_each_segment<Geometry>::apply(geometry, f);
+ dispatch::for_each_segment<Geometry>::apply(geometry, f);
+ return f;
 }
 
 

Modified: trunk/boost/geometry/multi/algorithms/for_each.hpp
==============================================================================
--- trunk/boost/geometry/multi/algorithms/for_each.hpp (original)
+++ trunk/boost/geometry/multi/algorithms/for_each.hpp 2012-11-18 14:51:00 EST (Sun, 18 Nov 2012)
@@ -40,13 +40,12 @@
 struct for_each_multi
 {
     template <typename MultiGeometry, typename Functor>
- static inline Functor apply(MultiGeometry& multi, Functor f)
+ static inline void apply(MultiGeometry& multi, Functor& f)
     {
         for(BOOST_AUTO_TPL(it, boost::begin(multi)); it != boost::end(multi); ++it)
         {
- f = Policy::apply(*it, f);
+ Policy::apply(*it, f);
         }
- return f;
     }
 };
 

Modified: trunk/libs/geometry/test/algorithms/test_for_each.hpp
==============================================================================
--- trunk/libs/geometry/test/algorithms/test_for_each.hpp (original)
+++ trunk/libs/geometry/test/algorithms/test_for_each.hpp 2012-11-18 14:51:00 EST (Sun, 18 Nov 2012)
@@ -11,6 +11,7 @@
 
 #include <geometry_test_common.hpp>
 
+#include <boost/config.hpp>
 #include <boost/geometry/algorithms/for_each.hpp>
 
 #include <boost/geometry/algorithms/distance.hpp>
@@ -87,9 +88,29 @@
 {
     typedef typename bg::point_type<Geometry>::type point_type;
 
+ // Class (functor)
     sum_x_functor<point_type> functor;
     functor = bg::for_each_point(geometry, functor);
     BOOST_CHECK_EQUAL(functor.sum, expected);
+
+
+ // Lambda
+#if !defined(BOOST_NO_CXX11_LAMBDAS)
+
+ typename bg::coordinate_type<point_type>::type sum_x = 0;
+
+ bg::for_each_point
+ (
+ geometry,
+ [&sum_x](point_type const& p)
+ {
+ sum_x += bg::get<0>(p);
+ }
+
+ );
+
+ BOOST_CHECK_EQUAL(sum_x, expected);
+#endif
 }
 
 template <typename Geometry>
@@ -97,6 +118,10 @@
     std::string const& expected1,
     std::string const& expected2)
 {
+#if !defined(BOOST_NO_CXX11_LAMBDAS)
+ Geometry copy = geometry;
+#endif
+
     typedef typename bg::point_type<Geometry>::type point_type;
 
     // function
@@ -119,6 +144,41 @@
         "for_each_point: "
         << " expected " << expected2
         << " got " << bg::wkt(geometry));
+
+#if !defined(BOOST_NO_CXX11_LAMBDAS)
+ // Lambda, both functions above together. Without / with capturing
+
+ geometry = copy;
+ bg::for_each_point
+ (
+ geometry,
+ [](point_type& p)
+ {
+ bg::set<0>(p, bg::get<0>(p) + 100);
+ }
+
+ );
+
+ typename bg::coordinate_type<point_type>::type scale = 100;
+ bg::for_each_point
+ (
+ geometry,
+ [&](point_type& p)
+ {
+ bg::set<1>(p, bg::get<1>(p) * scale);
+ }
+
+ );
+
+ std::ostringstream out3;
+ out3 << bg::wkt(geometry);
+
+ BOOST_CHECK_MESSAGE(out3.str() == expected2,
+ "for_each_point (lambda): "
+ << " expected " << expected2
+ << " got " << bg::wkt(geometry));
+#endif
+
 }
 
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk