[Polygon] "Ambiguous use of partial specialization" in CodeWarrior

I'm using a special version of CodeWarrior for an embedded system, but I suspect that other versions of the software will show the problem. The problem is, basically, the compiler hates polygon_traits<T>. Here's an example from polygon_90_set_traits.hpp: template <typename T> struct traits_by_concept<T, polygon_90_concept> { typedef polygon_traits<T> type; }; It chokes on the typedef, saying "Ambiguous use of partial specialization". This is the complete text of the error message; it provides no other information. Most of the surrounding definitions are very similar, but only the ones that use polygon_traits<T> -- instead of, say, rectangle_traits<T> -- raise errors. Here's another example from polygon_traits.hpp: template <typename T> struct view_of<rectangle_concept, T> { typedef typename polygon_traits<T>::coordinate_type coordinate_type; [snip] }; It chokes on the typedef and any code that tries to use the typedef. The same problem happens with all the other view_of functions and a couple of others, but all the problems seem to deal with the use of polygon_traits<T> in a template. Unfortunately, I know very little about partial specialization, traits classes, or any advanced features of generic programming in C++. My understanding of templates is limited to stuff like making basic containers, generalized sorting functions, etc. -- the easy stuff. So I find the definition of polygon_traits too complicated and am unable to fully comprehend the essence of the problem, let alone how to fix or work around it. Since I need to get this to work, if a proper solution is not obvious, I'm willing to accept any kind of clumsy hack, including disabling parts of the library that I might not need. (I use very little of the Polygon library, but I have a hard time finding an alternative to the part I do use -- namely, finding the union of polygons while allowing for holes. Alternative suggestions in that area are welcome, but I can't use GPLed code, or code that I would need to pay a license for to use commercially.) Any ideas? - Kef

Hi Kef,
I'm using a special version of CodeWarrior for an embedded system, but I suspect that other versions of the software will show the problem. The problem is, basically, the compiler hates polygon_traits<T>. Here's an example from polygon_90_set_traits.hpp:
[...] Probably Luke can help you with this. I cannot.
Since I need to get this to work, if a proper solution is not obvious, I'm willing to accept any kind of clumsy hack, including disabling parts of the library that I might not need. (I use very little of the Polygon library, but I have a hard time finding an alternative to the part I do use -- namely, finding the union of polygons while allowing for holes. Alternative suggestions in that area are welcome, but I can't use GPLed code, or code that I would need to pay a license for to use commercially.) You ask for an alternative, and there is one within Boost. You might look at Boost.Geometry, which has traits designed differently so maybe this problem will not occur. It is not tested in CodeWarrior though.
Sources are still here https://svn.boost.org/svn/boost/sandbox/ggl/formal_review and at our SVN. It has the union for polygons with holes. Regards, Barend

Barend Gehrels wrote:
You ask for an alternative, and there is one within Boost. You might look at Boost.Geometry, which has traits designed differently so maybe this problem will not occur. It is not tested in CodeWarrior though.
Sources are still here https://svn.boost.org/svn/boost/sandbox/ggl/formal_review and at our SVN.
It has the union for polygons with holes.
Have you implemented the multi-polygon interfaces for the union and intersection operations? Regards, Luke

Hi Luke, Simonson, Lucanus J wrote:
Barend Gehrels wrote:
You ask for an alternative, and there is one within Boost. You might look at Boost.Geometry, which has traits designed differently so maybe this problem will not occur. It is not tested in CodeWarrior though.
Sources are still here https://svn.boost.org/svn/boost/sandbox/ggl/formal_review and at our SVN.
It has the union for polygons with holes.
Have you implemented the multi-polygon interfaces for the union and intersection operations?
Polygons with holes (not being multi-polygons) are there already. I'm busy with the overlay operations, it is somewhat delayed but the plan was to have it in the sandbox again soon. Including multi's. Regards, Barend

Barend Gehrels wrote:
Hi Luke,
Simonson, Lucanus J wrote:
Barend Gehrels wrote:
You ask for an alternative, and there is one within Boost. You might look at Boost.Geometry, which has traits designed differently so maybe this problem will not occur. It is not tested in CodeWarrior though.
Sources are still here https://svn.boost.org/svn/boost/sandbox/ggl/formal_review and at our SVN.
It has the union for polygons with holes.
Have you implemented the multi-polygon interfaces for the union and intersection operations?
Polygons with holes (not being multi-polygons) are there already.
I'm busy with the overlay operations, it is somewhat delayed but the plan was to have it in the sandbox again soon. Including multi's.
Kef didn't specify whether he wanted to merge 2 polygons with holes or N polygons with holes. I would expect it is the latter. Interesting. What do you mean by overlay operations, exactly? Two layer map-overlay or N-layer? Thanks, Luke

Have you implemented the multi-polygon interfaces for the union and intersection operations?
Polygons with holes (not being multi-polygons) are there already.
I'm busy with the overlay operations, it is somewhat delayed but the plan was to have it in the sandbox again soon. Including multi's.
Kef didn't specify whether he wanted to merge 2 polygons with holes or N polygons with holes. I would expect it is the latter.
Interesting. What do you mean by overlay operations, exactly? Two layer map-overlay or N-layer?
Sorry, I interpreted your question wrongly. We call a multi polygon a geometry object having more than one polygon. That one is supported. N-layer will be supported once and is (theoretically) feasable by the same algorithm-set but not supported now. Overlay operations are currently still intersection / union, that state didn't change after review. Barend

Kef didn't specify whether he wanted to merge 2 polygons with holes or N polygons with holes. I would expect it is the latter.
I'm merging N polygons without holes into a set of polygons that may have holes. Actually, to be more specific, I'm only merging them at the edges; polygons that overlap, rather than merely touch, are rejected before the merge process. - Kef

Kef Schecter wrote:
Most of the surrounding definitions are very similar, but only the ones that use polygon_traits<T> -- instead of, say, rectangle_traits<T> -- raise errors.
Well, in that case you could try to add template <typename T> struct polygon_traits<T, gtl_no> {}; to the file polygon_traits.hpp below the lines 39ff template <typename T, typename enable = gtl_yes> struct polygon_traits {}; so that it looks similar to the definition of rectangle_traits... (But Barend is right of course that "Probably Luke can help you with this. I cannot.". I'm sure he will, but since he is in a different time zone he probably hasn't even read your message yet.) You could also try to compile the examples from the documentation, so that it would be clear that it is actually a problem of the library/compiler combination and not with your code itself. Regards, Thomas

On 1/8/2010 9:32 AM, Thomas Klimpel wrote:
Well, in that case you could try to add
template<typename T> struct polygon_traits<T, gtl_no> {};
to the file polygon_traits.hpp below the lines 39ff
template<typename T, typename enable = gtl_yes> struct polygon_traits {};
so that it looks similar to the definition of rectangle_traits...
It doesn't help, I'm afraid. I get exactly the same errors -- no more, no less.
You could also try to compile the examples from the documentation, so that it would be clear that it is actually a problem of the library/compiler combination and not with your code itself.
The problem occurs even in a .cpp file that does nothing but include polygon.hpp, so it can't be my code. Thanks, though. - Kef

Kef Schecter wrote:
It doesn't help, I'm afraid. I get exactly the same errors -- no more, no less.
I'll take another shoot at this. I patched polygon_traits.hpp a little to require less SFINAE "power" from the compiler. So can you try the attached patch to polygon_traits.hpp, and add the line #define BOOST_VERY_LITTLE_SFINAE before the line that contains the include statement for polygon.hpp? As a side note, the latest revision of Boost.Polygon doesn't pass all regression tests on MSVC-9.0 (basically the "std::map" from "typedef std::map<half_edge, property_map, less_half_edge> scanline_type;" complains at runtime that "less_half_edge" implements an "invalid operator<"). The last revision that works for me is r58551, the first revisions that fails for me is r58795. Regards, Thomas

I'll take another shoot at this. I patched polygon_traits.hpp a little to require less SFINAE "power" from the compiler.
So can you try the attached patch to polygon_traits.hpp, and add the line #define BOOST_VERY_LITTLE_SFINAE before the line that contains the include statement for polygon.hpp?
Hey, that did the trick! Thanks a ton. :) - Kef

Thomas Klimpel wrote:
Kef Schecter wrote:
It doesn't help, I'm afraid. I get exactly the same errors -- no more, no less.
I'll take another shoot at this. I patched polygon_traits.hpp a little to require less SFINAE "power" from the compiler.
So can you try the attached patch to polygon_traits.hpp, and add the line #define BOOST_VERY_LITTLE_SFINAE before the line that contains the include statement for polygon.hpp?
Wow, thanks! I'll take a look at your patch tomorrow and check in the changes. I have a new one week old at home, bringing the total to five children, and didn't get to Kef's problem yet except to verify what the issue was.
As a side note, the latest revision of Boost.Polygon doesn't pass all regression tests on MSVC-9.0 (basically the "std::map" from "typedef std::map<half_edge, property_map, less_half_edge> scanline_type;" complains at runtime that "less_half_edge" implements an "invalid operator<"). The last revision that works for me is r58551, the first revisions that fails for me is r58795.
The last three weeks I've been putting a lot of work into optimizing the general angle algorithms to minimize the use of infinite precision while maintaining robustness. The change to the less than operator is supposed to make comparisions of segments in the tree depend upon only my robust slope comparison predicate and not infinite precision calculations of precise coordinate values. I imagine there is some sort of runtime assertion baked into the MSVC stl that I'm failing. This is a bit surprising since the library is working quite well in my testing. I guess I'll have to update the code in my windows dev environment and chase this issue down. On the plus side, I've eliminated all use of infinite precision numerical data types for predicates and all but the case where long double fails for constructions. This means that the library is equally as fast with as without gmp robustness since long double fails only rarely with coordinates in the integer range. Thanks again, Luke

Thomas Klimpel wrote:
Kef Schecter wrote:
It doesn't help, I'm afraid. I get exactly the same errors -- no more, no less.
I'll take another shoot at this. I patched polygon_traits.hpp a little to require less SFINAE "power" from the compiler.
So can you try the attached patch to polygon_traits.hpp, and add the line #define BOOST_VERY_LITTLE_SFINAE before the line that contains the include statement for polygon.hpp?
From my reading of your patch you are selecting between the correct implementation of polygon_traits depending on the concept type of T without the use of SFINAE. It passes all my unit tests when BOOST_VERY_LITTLE_SFINAE is defined. It looks to me like I should just eliminate the #else clause and keep only your SFINAE-less compile time logic since it is feature complete and supported by more compilers. Also this eliminates the macro (and the need to document it.) Is there a reason you kept the SFINAE based code and used a macro to switch between the two other than to test your compile time logic against the original?
As a side note, the latest revision of Boost.Polygon doesn't pass all regression tests on MSVC-9.0 (basically the "std::map" from "typedef std::map<half_edge, property_map, less_half_edge> scanline_type;" complains at runtime that "less_half_edge" implements an "invalid operator<"). The last revision that works for me is r58551, the first revisions that fails for me is r58795.
fixed Thanks again, Luke

Simonson, Lucanus J wrote:
It looks to me like I should just eliminate the #else clause and keep only your SFINAE-less compile time logic since it is feature complete and supported by more compilers.
You could eliminate the #else clause, but I don't think that you should. After all, it is a workaround, and it is much more difficult to read than the original version, at least for me.
Also this eliminates the macro (and the need to document it.)
Oh, I guess that a compiler that already chokes when just including polygon.hpp will need much more code changes and workarounds than just this single traits definition. I tried this and downloaded a free special edition of a Freescale CodeWarrior compiler. It turns out that to even compile a file that only includes polygon.hpp without actually using it, the attached patch to scan_arbitrary.hpp is required. I didn't even try actually compiling one of the examples, but I guess that much more work would be required to get these compile.
Is there a reason you kept the SFINAE based code and used a macro to switch between the two other than to test your compile time logic against the original?
I guess that more workarounds will be required to port the SFINAE heavy Boost.Polygon code to a compiler with BOOST_VERY_LITTLE_SFINAE defined.
As a side note, the latest revision of Boost.Polygon doesn't pass all regression tests on MSVC-9.0 ...
fixed
Very good, I can confirm that the regression tests on MSVC-9.0 pass again. Regards, Thomas

Thomas Klimpel wrote:
Simonson, Lucanus J wrote:
It looks to me like I should just eliminate the #else clause and keep only your SFINAE-less compile time logic since it is feature complete and supported by more compilers.
You could eliminate the #else clause, but I don't think that you should. After all, it is a workaround, and it is much more difficult to read than the original version, at least for me.
Well, yes, it did take me a minute of looking at your code to figure out what it was doing. I was actually pretty impressed with the creativity of the template metaprogramming to select which type to inherit from to get all versions of polygon_traits to instantiate from a single definition. The original is sufficiently hard to read that only template meta-programming experts will have a chance. The users already have to rely on documentation and code examples to specialize polygon_traits.
Also this eliminates the macro (and the need to document it.)
Oh, I guess that a compiler that already chokes when just including polygon.hpp will need much more code changes and workarounds than just this single traits definition. I tried this and downloaded a free special edition of a Freescale CodeWarrior compiler. It turns out that to even compile a file that only includes polygon.hpp without actually using it, the attached patch to scan_arbitrary.hpp is required. I didn't even try actually compiling one of the examples, but I guess that much more work would be required to get these compile.
Yikes! I took a look at your patch to scan_arbitrary.hpp. If the CodeWarrior compiler can't find the functions in the templated base class from the context of a derived class then I'll have to qualify a huge number of function calls in several files. I use templated structs as proxy for templated namespace and derive from them to avoid having to fully qualify function calls. This pretty much makes that moot and I might as well not derive at all and just fully qualify everything. We should find out from Kef if he was successfully able to compile and use the algorithms with his variant of CodeWarrior.
Is there a reason you kept the SFINAE based code and used a macro to switch between the two other than to test your compile time logic against the original?
I guess that more workarounds will be required to port the SFINAE heavy Boost.Polygon code to a compiler with BOOST_VERY_LITTLE_SFINAE defined.
Is BOOST_VERY_LITTLE_SFINAE a real boost macro, or just a joke Dave made last time CodeWarrior was discussed?
As a side note, the latest revision of Boost.Polygon doesn't pass all regression tests on MSVC-9.0 ...
fixed
Very good, I can confirm that the regression tests on MSVC-9.0 pass again.
I have also performed pseudo-exhaustive testing on large scale randomly generated inputs. The library is currently passing these tests and running faster with GMP to provide 100% robustness than it did without GMP at the time it was reviewed. Anyone using the library currently who isn't using GMP due to performance concerns should update now, because the code currently checked in to the sandbox is well tested. Thanks, Luke

Kef Schecter wrote:
I'm using a special version of CodeWarrior for an embedded system, but I suspect that other versions of the software will show the problem. The problem is, basically, the compiler hates polygon_traits<T>. Here's an example from polygon_90_set_traits.hpp:
template <typename T> struct traits_by_concept<T, polygon_90_concept> { typedef polygon_traits<T> type; };
It chokes on the typedef, saying "Ambiguous use of partial specialization". This is the complete text of the error message; it provides no other information.
Does anyone know how well CodeWarrior supports SFINE in the context of instantiating a template struct? I have several partial specializations of polygon_traits and I use SFINAE in the 2nd template parameter to select between them based on the concept type of the 1st template parameter. This glues the whole polygon typesystem together and provides the mappings between concepts and their refinements. Based on a quick search I found this comment: " Not AFAICT; I tried that. Also, the use of enable_if in the iterators library proves that inheritance doesn't hurt CWPro8. It looks to me like on CWPro8, SFINAE is only good for eliminating overloads, and the other uses fail. -- Dave Abrahams Boost Consulting www.boost-consulting.com " Kef, what version of CodeWarrior does your special version derive from? Thanks, Luke

On 1/8/2010 1:33 PM, Simonson, Lucanus J wrote:
Kef, what version of CodeWarrior does your special version derive from?
The command line compiler reports: Freescale C/C++ for Embedded ARM. Copyright (c) 2009, Freescale Semiconductor, Inc All rights reserved. Version 4.0 build 1027 (build 1027) Runtime Built: Oct 12 2009 18:12:25 I have no idea how that might correspond to other versions of CodeWarrior, though. - Kef
participants (4)
-
Barend Gehrels
-
Kef Schecter
-
Simonson, Lucanus J
-
Thomas Klimpel