Dear Experts,
This is a question about Boost.Polygon but please keep reading
even if you've never used that library as it's really just about
how to resolve ambiguous template specialisations.
Boost.Polygon has a mechanism by which you can tell it about
your own types by specialising templates. I want to tell it that
std::array is a polygon, which I try to do like this:
template
struct geometry_concept< std::array >
{
using type = polygon_concept;
};
template
struct polygon_traits< std::array >
{ ....... };
This doesn't work because of ambiguity between that specialisation
of polygon_traits and a default specialization that is in the library
itself; the library code looks something like this:
template
struct polygon_traits {};
template <typename T>
struct polygon_traits
{ ......... };
If I try to just specialize one size of array it works:
template <>
struct polygon_traits< std::arrayg2i::Point,3 >
{ ....... };
The error is:
test_template_specialization.cc:64:19: error: ambiguous partial specializations of 'polygon_traits, boost::polygon::gtl_yes>'
boost::polygon::polygon_traits>::iterator_type i = nullptr;
^
/usr/local/include/boost/polygon/polygon_traits.hpp:100:10: note: partial specialization matches [with T = std::__1::array]
struct polygon_traits >
^
I have the same issue when I attempt to use a Point class that
takes the coordinate type as a template parameter.
Can anyone suggest how I can write my specialisations so that they
are unambiguous?
A complete test program follows. I'm testing with Boost 1.69.0, but
I don't think anything has changed in Polygon since then.
Thanks, Phil.
#include
#include <array>
struct Point { int x; int y; };
namespace boost { namespace polygon {
template <>
struct geometry_concept<Point>
{
using type = point_concept;
};
template <>
struct point_traits<Point>
{
using coordinate_type = int;
static inline coordinate_type get(const Point& point, orientation_2d orient)
{
return (orient==HORIZONTAL) ? point.x : point.y;
}
};
template
struct geometry_concept< std::array >
{
using type = polygon_concept;
};
template
struct polygon_traits< std::array >
{
using coordinate_type = int;
using iterator_type = typename std::array::const_iterator;
using point_type = Point;
static inline iterator_type begin_points(const std::array& p)
{
return p.begin();
}
static inline iterator_type end_points(const std::array& p)
{
return p.end();
}
static inline std::size_t size(const std::array&)
{
return N;
}
static inline winding_direction winding(const std::array&)
{
return unknown_winding; // Hmm.
}
};
}; }; // namespace boost, polygon
int main()
{
boost::polygon::polygon_traits>::iterator_type i = nullptr;
return 0;
}