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<Point,N> is a polygon, which I try to do like this: template <size_t N> struct geometry_concept< std::array<Point,N> > { using type = polygon_concept; }; template <size_t N> struct polygon_traits< std::array<Point,N> > { ....... }; 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 <typename T, typename enable = gtl_yes> struct polygon_traits {}; template <typename T> struct polygon_traits<T, ...some SFINAE stuff.... > { ......... }; If I try to just specialize one size of array it works: template <> struct polygon_traits< std::array<g2i::Point,3> > { ....... }; The error is: test_template_specialization.cc:64:19: error: ambiguous partial specializations of 'polygon_traits<std::__1::array<Point, 3>, boost::polygon::gtl_yes>' boost::polygon::polygon_traits<std::array<Point,3>>::iterator_type i = nullptr; ^ /usr/local/include/boost/polygon/polygon_traits.hpp:100:10: note: partial specialization matches [with T = std::__1::array<Point, 3>] struct polygon_traits<T, ^ test_template_specialization.cc:32:8: note: partial specialization matches [with N = 3] struct polygon_traits< std::array<Point,N> > ^ 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 <boost/polygon/polygon.hpp> #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 <size_t N> struct geometry_concept< std::array<Point,N> > { using type = polygon_concept; }; template <size_t N> struct polygon_traits< std::array<Point,N> > { using coordinate_type = int; using iterator_type = typename std::array<Point,N>::const_iterator; using point_type = Point; static inline iterator_type begin_points(const std::array<Point,N>& p) { return p.begin(); } static inline iterator_type end_points(const std::array<Point,N>& p) { return p.end(); } static inline std::size_t size(const std::array<Point,N>&) { return N; } static inline winding_direction winding(const std::array<Point,N>&) { return unknown_winding; // Hmm. } }; }; }; // namespace boost, polygon int main() { boost::polygon::polygon_traits<std::array<Point,3>>::iterator_type i = nullptr; return 0; }