1 // Boost.Geometry 2 3 // Copyright (c) 2021, Oracle and/or its affiliates. 4 5 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle 6 7 // Licensed under the Boost Software License version 1.0. 8 // http://www.boost.org/users/license.html 9 10 #ifndef BOOST_GEOMETRY_CORE_VISIT_HPP 11 #define BOOST_GEOMETRY_CORE_VISIT_HPP 12 13 #include <utility> 14 15 #include <boost/range/value_type.hpp> 16 17 #include <boost/geometry/core/static_assert.hpp> 18 #include <boost/geometry/util/type_traits_std.hpp> 19 20 21 namespace boost { namespace geometry { namespace traits 22 { 23 24 // TODO: Alternatives: 25 // - free function 26 // template <typename Visitor, typename ...Variants> 27 // auto visit(Visitor &&, Variants && ...) {} 28 // 29 // - additional Enable tparam 30 // template <bool Enable, typename ...DynamicGeometries> 31 // struct visit {}; 32 33 template <typename ...DynamicGeometries> 34 struct visit 35 { 36 BOOST_GEOMETRY_STATIC_ASSERT_FALSE( 37 "Not implemented for these DynamicGeometries types.", 38 DynamicGeometries...); 39 }; 40 41 // By default call 1-parameter visit for each geometry 42 template <typename DynamicGeometry1, typename DynamicGeometry2> 43 struct visit<DynamicGeometry1, DynamicGeometry2> 44 { 45 template <typename Function, typename Variant1, typename Variant2> applyboost::geometry::traits::visit46 static void apply(Function && function, Variant1 && variant1, Variant2 && variant2) 47 { 48 visit<util::remove_cref_t<Variant1>>::apply([&](auto && g1) 49 { 50 using ref1_t = decltype(g1); 51 visit<util::remove_cref_t<Variant2>>::apply([&](auto && g2) 52 { 53 function(std::forward<ref1_t>(g1), 54 std::forward<decltype(g2)>(g2)); 55 }, std::forward<Variant2>(variant2)); 56 }, std::forward<Variant1>(variant1)); 57 } 58 }; 59 60 // By default treat GeometryCollection as a range of DynamicGeometries 61 template <typename GeometryCollection> 62 struct iter_visit 63 { 64 template <typename Function, typename Iterator> applyboost::geometry::traits::iter_visit65 static void apply(Function && function, Iterator iterator) 66 { 67 using value_t = typename boost::range_value<GeometryCollection>::type; 68 using reference_t = typename std::iterator_traits<Iterator>::reference; 69 visit<value_t>::apply(std::forward<Function>(function), 70 std::forward<reference_t>(*iterator)); 71 } 72 }; 73 74 }}} // namespace boost::geometry::traits 75 76 #endif // BOOST_GEOMETRY_CORE_VISIT_HPP 77