// Boost.Geometry // Copyright (c) 2019-2020, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { // true for any geometry template struct is_geometry : boost::integral_constant < bool, (! boost::is_void::type>::value) > {}; // true for multi-point, multi-linestring or multi-polygon template struct is_multi_geometry : boost::is_base_of < geometry::multi_tag, typename geometry::tag::type > {}; // true for point, linestring or polygon template struct is_multi_geometry_value : boost::integral_constant < bool, ((boost::is_same::type, point_tag>::value) || (boost::is_same::type, linestring_tag>::value) || (boost::is_same::type, polygon_tag>::value)) > {}; template struct is_range_impl { typedef boost::type_traits::yes_type yes_type; typedef boost::type_traits::no_type no_type; template static yes_type test(typename boost::range_iterator::type*); template static no_type test(...); static const bool value = (sizeof(test(0)) == sizeof(yes_type)); }; // true if T is range (boost::range_iterator::type is defined) template struct is_range : boost::integral_constant::value> {}; // geometry tag of Rng value_type template struct range_value_tag : geometry::tag::type> {}; // true if geometry tag of Rng is the same as Tag template struct is_range_value_tag_same_as : boost::is_same < typename range_value_tag::type, Tag > {}; template ::value> struct is_tupled_output_element_base : boost::integral_constant {}; template struct is_tupled_output_element_base : boost::integral_constant < bool, (is_multi_geometry::value || ((! is_geometry::value) && ((is_range_value_tag_same_as::value) || (is_range_value_tag_same_as::value) || (is_range_value_tag_same_as::value)))) > {}; // true if T is a multi-geometry or is a range of points, linestrings or // polygons template struct is_tupled_output_element : is_tupled_output_element_base {}; // true if Output is not a geometry (so e.g. tuple was not adapted to any // concept) and at least one of the tuple elements is a multi-geometry or // a range of points linestrings or polygons template struct is_tupled_output_check : boost::mpl::and_ < boost::is_same::type, void>, //geometry::tuples::exists_if geometry::tuples::exists_if > {}; // true if T is a point, linestring or polygon template struct is_tupled_range_values_element : boost::integral_constant < bool, ((boost::is_same::type, point_tag>::value) || (boost::is_same::type, linestring_tag>::value) || (boost::is_same::type, polygon_tag>::value)) > {}; // true if T is not a geometry (so e.g. tuple was not adapted to any // concept) and at least one of the tuple elements is a point, linesting // or polygon template struct is_tupled_range_values_check : boost::mpl::and_ < boost::is_same::type, void>, geometry::tuples::exists_if > {}; // true if Output is boost::tuple, boost::tuples::cons, std::pair or std::tuple template struct is_tupled : boost::integral_constant {}; template < class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9 > struct is_tupled > : boost::integral_constant {}; template struct is_tupled > : boost::integral_constant {}; template struct is_tupled > : boost::integral_constant {}; #ifdef BOOST_GEOMETRY_CXX11_TUPLE template struct is_tupled > : boost::integral_constant {}; #endif // BOOST_GEOMETRY_CXX11_TUPLE // true if Output is boost::tuple, boost::tuples::cons, std::pair or std::tuple // and is_tupled_output_check defiend above passes template ::value> struct is_tupled_output : boost::integral_constant {}; template struct is_tupled_output : is_tupled_output_check {}; // true if T is boost::tuple, boost::tuples::cons, std::pair or std::tuple // and is_tupled_range_values_check defiend above passes template ::value> struct is_tupled_range_values : boost::integral_constant {}; template struct is_tupled_range_values : is_tupled_range_values_check {}; template struct tupled_output_find_index_pred { template struct pred : boost::is_same::type, Tag> {}; }; // Valid only if tupled_output_has is true template struct tupled_output_find_index : geometry::tuples::find_index_if < Output, tupled_output_find_index_pred::template pred > {}; template < typename Output, typename Tag, bool IsTupledOutput = is_tupled_output::value > struct tupled_output_has : boost::integral_constant {}; template struct tupled_output_has : boost::integral_constant < bool, ((tupled_output_find_index::value) < (geometry::tuples::size::value)) > {}; // Valid only if tupled_output_has is true template inline typename geometry::tuples::element < tupled_output_find_index::value, Output >::type & tupled_output_get(Output & output) { return geometry::tuples::get::value>(output); } // defines a tuple-type holding value-types of ranges being elements of // Output pair/tuple template < typename Tuple, size_t I = 0, size_t N = geometry::tuples::size::value > struct tupled_range_values_bt { typedef boost::tuples::cons < typename boost::range_value < typename geometry::tuples::element::type >::type, typename tupled_range_values_bt::type > type; }; template struct tupled_range_values_bt { typedef boost::tuples::null_type type; }; template struct tupled_range_values : tupled_range_values_bt {}; template struct tupled_range_values > { typedef std::pair < typename boost::range_value::type, typename boost::range_value::type > type; }; #ifdef BOOST_GEOMETRY_CXX11_TUPLE template struct tupled_range_values > { typedef std::tuple::type...> type; }; #endif // BOOST_GEOMETRY_CXX11_TUPLE // util defining a type and creating a tuple holding back-insert-iterators to // ranges being elements of Output pair/tuple template ::value> struct tupled_back_inserters_bt { typedef boost::tuples::cons < geometry::range::back_insert_iterator < typename geometry::tuples::element::type >, typename tupled_back_inserters_bt::type > type; static type apply(Tuple & tup) { return type(geometry::range::back_inserter(geometry::tuples::get(tup)), tupled_back_inserters_bt::apply(tup)); } }; template struct tupled_back_inserters_bt { typedef boost::tuples::null_type type; static type apply(Tuple const&) { return type(); } }; template struct tupled_back_inserters : tupled_back_inserters_bt {}; template struct tupled_back_inserters > { typedef std::pair < geometry::range::back_insert_iterator, geometry::range::back_insert_iterator > type; static type apply(std::pair & p) { return type(geometry::range::back_inserter(p.first), geometry::range::back_inserter(p.second)); } }; #ifdef BOOST_GEOMETRY_CXX11_TUPLE // NOTE: In C++14 std::integer_sequence and std::make_integer_sequence could be used template struct tupled_back_inserters_st; template struct tupled_back_inserters_st, std::tuple > { typedef std::tuple...> type; static type apply(std::tuple & tup) { return type(geometry::range::back_inserter(std::get(tup))...); } }; template struct tupled_back_inserters > : tupled_back_inserters_st < typename geometry::tuples::make_int_sequence::type, std::tuple > {}; #endif // BOOST_GEOMETRY_CXX11_TUPLE template < typename GeometryOut, bool IsTupled = is_tupled_output::value > struct output_geometry_value : boost::range_value {}; template struct output_geometry_value : tupled_range_values {}; template < typename GeometryOut, bool IsTupled = is_tupled_output::value > struct output_geometry_back_inserter_ { typedef geometry::range::back_insert_iterator type; static type apply(GeometryOut & out) { return geometry::range::back_inserter(out); } }; template struct output_geometry_back_inserter_ : tupled_back_inserters {}; template inline typename output_geometry_back_inserter_::type output_geometry_back_inserter(GeometryOut & out) { return output_geometry_back_inserter_::apply(out); } // is_tag_same_as_pred // Defines a predicate true if type's tag is the same as Tag template struct is_tag_same_as_pred { template struct pred : boost::is_same::type, Tag> {}; }; // Allows to access a type/object in a pair/tuple corresponding to an index in // GeometryOut pair/tuple of a geometry defined by Tag. // If GeometryOut is a geometry then it's expected to be defined by DefaultTag. template < typename GeometryOut, typename Tag, typename DefaultTag, typename GeometryTag = typename geometry::tag::type > struct output_geometry_access {}; // assume GeometryTag is void because not adapted tuple holding geometries was passed template struct output_geometry_access { static const int index = geometry::tuples::find_index_if < TupledOut, is_tag_same_as_pred::template pred >::value; typedef typename geometry::tuples::element::type type; template static typename geometry::tuples::element::type& get(Tuple & tup) { return geometry::tuples::get(tup); } }; template struct output_geometry_access { typedef GeometryOut type; template static T& get(T & v) { return v; } }; } // namespace detail #endif // DOXYGEN_NO_DETAIL }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP