|
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