From 75ceb8586d586e639089ab41af42d22054a8d52e Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Sun, 3 May 2015 15:42:15 +0200 Subject: [PATCH 1/4] [algorithms] Add lazy_no_implemented and use it in within. For variants throw an exception depending on the supported combinations instead of a compile-time assert failure. --- .../boost/geometry/algorithms/not_implemented.hpp | 60 +++++++++++++++++++++- include/boost/geometry/algorithms/within.hpp | 57 ++++++++++++++++---- 2 files changed, 106 insertions(+), 11 deletions(-) diff --git a/include/boost/geometry/algorithms/not_implemented.hpp b/include/boost/geometry/algorithms/not_implemented.hpp index 9c416074ed..b55eca6659 100644 --- a/include/boost/geometry/algorithms/not_implemented.hpp +++ b/include/boost/geometry/algorithms/not_implemented.hpp @@ -20,6 +20,7 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP #define BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP +#include #include #include @@ -96,7 +97,7 @@ template <> struct tag_to_term { typedef info::GEOM template struct tag_to_term > { typedef info::DIMENSION type; }; -} +} // namespace nyi template @@ -125,6 +126,63 @@ struct not_implemented {}; +template +< + typename Result, + typename Term1 = void, + typename Term2 = void, + typename Term3 = void +> +struct lazy_not_implemented + : nyi::not_implemented_tag +{ +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + static inline Result apply(T1 const&...) + { + not_implemented(); + return Result(); + } +#else + static inline Result apply() + { + not_implemented(); + return Result(); + } + + template + static inline Result apply(T1 const&, T2 const&) + { + not_implemented(); + return Result(); + } + + template + static inline Result apply(T1 const&, T2 const&, T3 const&) + { + not_implemented(); + return Result(); + } + + template + static inline Result apply(T1 const&, T2 const&, T3 const&, T4 const&) + { + not_implemented(); + return Result(); + } +#endif +}; + + +struct not_implemented_exception + : boost::geometry::exception +{ + const char * what() const + { + return "THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED for passed input types"; + } +}; + }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/within.hpp b/include/boost/geometry/algorithms/within.hpp index 9f2b6fedf7..ddfe2a112f 100644 --- a/include/boost/geometry/algorithms/within.hpp +++ b/include/boost/geometry/algorithms/within.hpp @@ -96,7 +96,8 @@ template typename Tag2 = typename tag::type > struct within - : not_implemented + //: not_implemented + : lazy_not_implemented {}; @@ -349,6 +350,39 @@ struct within } }; +template +< + typename Geometry1, + typename Geometry2, + bool NotImplemented = boost::is_base_of + < + nyi::not_implemented_tag, + dispatch::within + >::value +> +struct within_variant +{ + template + static inline bool apply(Geometry1 const& geometry1, + Geometry2 const& geometry2, + Strategy const& strategy) + { + return within::apply(geometry1, geometry2, strategy); + } +}; + +template +struct within_variant +{ + template + static inline bool apply(Geometry1 const& , + Geometry2 const& , + Strategy const& ) + { + throw geometry::not_implemented_exception(); + } +}; + template struct within, Geometry2> { @@ -366,9 +400,10 @@ struct within, Geometry2> template bool operator()(Geometry1 const& geometry1) const { - return within::apply(geometry1, - m_geometry2, - m_strategy); + return within_variant + < + Geometry1, Geometry2 + >::apply(geometry1, m_geometry2, m_strategy); } }; @@ -402,9 +437,10 @@ struct within > template bool operator()(Geometry2 const& geometry2) const { - return within::apply(m_geometry1, - geometry2, - m_strategy); + return within_variant + < + Geometry1, Geometry2 + >::apply(m_geometry1, geometry2, m_strategy); } }; @@ -441,9 +477,10 @@ struct within< bool operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const { - return within::apply(geometry1, - geometry2, - m_strategy); + return within_variant + < + Geometry1, Geometry2 + >::apply(geometry1, geometry2, m_strategy); } }; From c0fbc55d91484486013c41309571f6e37278f9ff Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 5 May 2015 20:02:21 +0200 Subject: [PATCH 2/4] [algorithms] Add is_not_implemented util and use it in within. --- .../geometry/algorithms/is_not_implemented.hpp | 190 +++++++++++++++++++++ include/boost/geometry/algorithms/within.hpp | 22 ++- 2 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 include/boost/geometry/algorithms/is_not_implemented.hpp diff --git a/include/boost/geometry/algorithms/is_not_implemented.hpp b/include/boost/geometry/algorithms/is_not_implemented.hpp new file mode 100644 index 0000000000..6b36268171 --- /dev/null +++ b/include/boost/geometry/algorithms/is_not_implemented.hpp @@ -0,0 +1,190 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_IS_NOT_IMPLEMENTED_HPP +#define BOOST_GEOMETRY_ALGORITHMS_IS_NOT_IMPLEMENTED_HPP + + +#include +#include +#include +#include +#include +#include + +#include + + +namespace boost { namespace geometry { + +namespace detail { namespace is_not_implemented { + +template +< + typename Seq, + typename MetaPred, + typename PrevState, + typename First = typename boost::mpl::begin::type, + typename Last = typename boost::mpl::end::type +> +struct for_each +{ + typedef typename for_each + < + Seq, + MetaPred, + typename MetaPred::template apply + < + typename boost::mpl::deref::type, + PrevState + >, + typename boost::mpl::next::type, + Last + >::type type; +}; + +template +< + typename Seq, + typename MetaPred, + typename PrevState, + typename Last +> +struct for_each +{ + typedef PrevState type; +}; + +template +struct reverse +{ + template + struct apply + : MetaPolicy::template apply + {}; +}; + +template +struct metapred +{ + template + struct apply + : boost::mpl::bool_ + < + PrevState::value && + MetaPolicy::template apply::value + > + {}; +}; + +template +struct metapred_2 +{ + template + struct apply + : boost::mpl::bool_ + < + PrevState::value && + for_each + < + Seq2, + metapred, + boost::mpl::bool_ + >::type::value + > + {}; +}; + +}} // namespace detail::is_not_implemented + + +/*! + A utility for checking if an algorithm is not implemented for some Geometries. + For variants it checks all combinations of Geometries and sets value to false + only if all combinations are not implemented. + */ +template +struct is_not_implemented + : MetaPolicy::template apply +{}; + +template +< + typename Geometry1, + BOOST_VARIANT_ENUM_PARAMS(typename T), + typename MetaPolicy +> +struct is_not_implemented + < + Geometry1, + boost::variant, + MetaPolicy + > + : detail::is_not_implemented::for_each + < + typename boost::variant::types, + detail::is_not_implemented::metapred, + boost::mpl::bool_ + >::type +{}; + +template +< + BOOST_VARIANT_ENUM_PARAMS(typename T), + typename Geometry2, + typename MetaPolicy +> +struct is_not_implemented + < + boost::variant, + Geometry2, + MetaPolicy + > + : detail::is_not_implemented::for_each + < + typename boost::variant::types, + detail::is_not_implemented::metapred + < + Geometry2, + detail::is_not_implemented::reverse + >, + boost::mpl::bool_ + >::type +{}; + +template +< + BOOST_VARIANT_ENUM_PARAMS(typename T1), + BOOST_VARIANT_ENUM_PARAMS(typename T2), + typename MetaPolicy +> +struct is_not_implemented + < + boost::variant, + boost::variant, + MetaPolicy + > + : detail::is_not_implemented::for_each + < + typename boost::variant::types, + detail::is_not_implemented::metapred_2 + < + typename boost::variant::types, + MetaPolicy + >, + boost::mpl::bool_ + >::type +{ +}; + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_IS_NOT_IMPLEMENTED_HPP diff --git a/include/boost/geometry/algorithms/within.hpp b/include/boost/geometry/algorithms/within.hpp index ddfe2a112f..92c045fce7 100644 --- a/include/boost/geometry/algorithms/within.hpp +++ b/include/boost/geometry/algorithms/within.hpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -350,14 +351,29 @@ struct within } }; + +struct within_metapolicy +{ + template + struct apply + : boost::is_base_of + < + nyi::not_implemented_tag, + dispatch::within + > + {}; +}; + + template < typename Geometry1, typename Geometry2, - bool NotImplemented = boost::is_base_of + bool NotImplemented = is_not_implemented < - nyi::not_implemented_tag, - dispatch::within + Geometry1, + Geometry2, + within_metapolicy >::value > struct within_variant From 60e5f138dd90f26ff9a79603c066f71047e232ef Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 5 May 2015 20:02:58 +0200 Subject: [PATCH 3/4] [algorithms] Tweak lazy not_implemented and fix not_implemented_exception. Specialize lazy_not_implemented for void Result. Add throw() exception specification to not_implemented_exception::which(). --- .../boost/geometry/algorithms/not_implemented.hpp | 41 ++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/include/boost/geometry/algorithms/not_implemented.hpp b/include/boost/geometry/algorithms/not_implemented.hpp index b55eca6659..147ddb23cf 100644 --- a/include/boost/geometry/algorithms/not_implemented.hpp +++ b/include/boost/geometry/algorithms/not_implemented.hpp @@ -8,6 +8,7 @@ // Modifications copyright (c) 2015, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -128,7 +129,7 @@ struct not_implemented template < - typename Result, + typename Result = void, typename Term1 = void, typename Term2 = void, typename Term3 = void @@ -173,11 +174,47 @@ struct lazy_not_implemented #endif }; +template +struct lazy_not_implemented + : nyi::not_implemented_tag +{ +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + static inline void apply(T1 const&...) + { + not_implemented(); + } +#else + static inline void apply() + { + not_implemented(); + } + + template + static inline void apply(T1 const&, T2 const&) + { + not_implemented(); + } + + template + static inline void apply(T1 const&, T2 const&, T3 const&) + { + not_implemented(); + } + + template + static inline void apply(T1 const&, T2 const&, T3 const&, T4 const&) + { + not_implemented(); + } +#endif +}; + struct not_implemented_exception : boost::geometry::exception { - const char * what() const + const char * what() const throw() { return "THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED for passed input types"; } From c7eff7b929b4c3cccd7a0b812007c4621ca9aba3 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Tue, 5 May 2015 20:06:36 +0200 Subject: [PATCH 4/4] [test][within][not_implemented] Add test for within implementation status check. --- .../relational_operations/within/Jamfile.v2 | 1 + .../within/within_not_implemented.cpp | 127 +++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 test/algorithms/relational_operations/within/within_not_implemented.cpp diff --git a/test/algorithms/relational_operations/within/Jamfile.v2 b/test/algorithms/relational_operations/within/Jamfile.v2 index dc33b40cc3..14d74030bd 100644 --- a/test/algorithms/relational_operations/within/Jamfile.v2 +++ b/test/algorithms/relational_operations/within/Jamfile.v2 @@ -21,5 +21,6 @@ test-suite boost-geometry-algorithms-within [ run within_areal_areal.cpp ] [ run within_linear_areal.cpp ] [ run within_linear_linear.cpp ] + [ run within_not_implemented.cpp ] [ run within_pointlike_xxx.cpp ] ; diff --git a/test/algorithms/relational_operations/within/within_not_implemented.cpp b/test/algorithms/relational_operations/within/within_not_implemented.cpp new file mode 100644 index 0000000000..c2b8cb0eae --- /dev/null +++ b/test/algorithms/relational_operations/within/within_not_implemented.cpp @@ -0,0 +1,127 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2014, 2015. +// Modifications copyright (c) 2014-2015 Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include "test_within.hpp" + +#include +#include + + +bool true_pred(bg::not_implemented_exception const&) { return true; } + + +int test_main( int , char* [] ) +{ + typedef bg::model::d2::point_xy pt_t; + typedef bg::model::multi_point mpt_t; + typedef bg::model::linestring ls_t; + typedef bg::model::ring ring_t; + typedef bg::model::polygon poly_t; + typedef bg::model::multi_polygon mpoly_t; + + typedef boost::variant var_pt_t; + typedef boost::variant var_po_t; + typedef boost::variant var_pt_po_t; + typedef boost::variant var_po_pt_t; + + pt_t pt(1, 1); + poly_t poly; + boost::geometry::read_wkt("POLYGON((0 0,0 5,5 5,5 0,0 0))", poly); + + var_pt_po_t v1 = pt; + var_pt_po_t v2 = pt; + var_pt_po_t v3 = poly; + + BOOST_CHECK(bg::within(v1, v2)); + BOOST_CHECK(bg::within(v1, v3)); + BOOST_CHECK_EXCEPTION(bg::within(v3, v1), + bg::not_implemented_exception, + true_pred); + + using bg::resolve_variant::within_metapolicy; + + // sanity check + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK(!(within_metapolicy::apply::value)); + BOOST_CHECK(!(within_metapolicy::apply::value)); + BOOST_CHECK(!(within_metapolicy::apply::value)); + + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + + typedef boost::variant var_p_ls_t; + typedef boost::variant var_a_t; + typedef boost::variant var_p_ls_po_t; + typedef boost::variant var_ls_a_t; + + // sanity check + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + BOOST_CHECK( (within_metapolicy::apply::value)); + + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK( (bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + BOOST_CHECK(!(bg::is_not_implemented::value)); + + return 0; +}