
Bruno, I'm happy to hear from you again! Luke wrote:
You do raise a valid point, there is currently no concept checking included in the design and implementation I checked into the sandbox. Is it valid to call something a concept if there is no concept checking?
Bruno wrote:
Yes it is. But in my opinion, showing up a concept class has the advantage of clearly communicating the intention to the community in order to validate / invalidate the design. Moreover, since two geometry-related libraries are currently being developed for Boost (even if they don't do the same things) I think comparing the concepts used would allow us to see exactly what are the convergences / divergences, and see what can or cannot be done to make them as close as possible. A certain level of consistency between those libraries would surely be appreciated.
In fact I am thinking much more along these lines than you may realize. Given my proposed operator syntax for so-called Boolean operations I could fold the arbitrary angle geometry provided by Berend's library into mine (or visa-vera.) manhattan + manhattan => manhattan result type by way of manhattan algorithm manhattan + 45-degree => 45-degree result type by way of 45 degree algorithm manhattan/45-degree + arbitrary angle => arbitrary angle result by way of arbitrary angle algorithm with all the concept checking and tag dispatching taken care of by the API to select the correct algorithms and return types for the given input arguments and operations. Whether that arbitrary angle algorithm comes from Barend's library or the geos library (C++ port of the famous JKT java geometry library) seems like an open question to me. Geos is attractive as an alternative to cgal for those of us who cannot stomach cgal's qpl license. geos' lgpl is more restrictive than boost license, but I think we could provide a generic framework for plugging in lgpl'd algorithms to my API at link time to integrate the two. It could then plug in cgal algorithms for that matter, provided that the person doing the linking was allowed to use them (paid for the privledge or is academic or whatever.) This whole issue becomes complex since there are many libraries that do similar things to Barend's. The last open source library that did manhattan geometry operations was the fang library written in 1980 in C. It is next to worthless now that we've come so far with algorithms and data structures (and C++). Bruno wrote:
Barend and me have written the following point concept (it's obviously open to criticism):
template <class X> struct Point { typedef typename point_traits<X>::coordinate_type ctype; enum { ccount = point_traits<X>::coordinate_count };
template <class P, int I, int Count> struct dimension_checker { static void check() { const P* point; ctype coord = point_traits<X>::template get<I>(*point); P* point2; point_traits<X>::template get<I>(*point2) = coord;
dimension_checker<P, I+1, Count>::check(); } };
template <class P, int Count> struct dimension_checker<P, Count, Count> { static void check() {} };
BOOST_CONCEPT_USAGE(Point) { dimension_checker<X, 0, ccount>::check(); } };
It actually forwards everything to the point_traits class in order to check that everything needed is accessible through point traits for the point type begin checked. Since you rely on point traits too, I suppose you would have the same approach?
Yes, my own is very similar to what you show, except that I think n-dimensional point classes are pointless exercise, if you'll excuse the bad pun. What exactly is the benefit of making the order of the point data type generic? Are we saving typing in the library by merging the 2D and 3D point concepts? Do we pay a penalty for that? In your case you may not be paying a penalty because you are using compile time integer to index the point. You also provide compile time checking to make source the index is valid, I see, which is good. In my case, I have the rich language of isotropy that performs runtime indexing. There are separate index types for 2 and 3d geometry and type safety prevents an invalid 3d index from being used with a 2d type. The language of isotropy provides a different kind of abstraction than what you are doing abstracting away the order of the point. The question that leaves us with is which abstraction is more valuable to the user, since they are mutually exclusive. Isotropy is quite valuable to the user, and we get very good results (in terms of code quality and productivity) using it. I doubt the user will parameterize the order of their own code, so the benefit of doing so in your library will be confined to the internal implementation of the library itself, unless I am mistaken. Bruno wrote:
If you don't want to do that right now because you're afraid about the profusion of concept checking macros in your code, I think that putting a BOOST_CONCEPT_ASSERT in the point_traits class is sufficient with this approach, since any access to a point should be performed only through this class. This way, you don't have to rewrite the check in every algorithm, and the only job you have to do is writing the concept class. However, as I'm not used yet with the BCCL, I can be wrong...?
I don't know. I was deferring adding the checks until the design is finished, since they would change as the design changes. Also, my point_concept is a little more overloaded than yours might be. I use the concept type as a tag for tag dispatching purposes. I also use it as a sort-of namespace for holding all the functions related to the point concept. I pass it as a template parameter to select which concept to apply and I return it as the result of a meta function call to deduce the concept type for a given user type. It is therefore much more than a traditional "minimal" concept such as in the stl. Moreover, I want to allow partial modeling of the concept, for instance, if a data type doesn't provide a default constructor, or even allow modification of it's data through the traits it should still be allowed to work as a read-only geometry type when those services are not needed. It is, therefore, improper to check that the data type conforms to the full requirements of the concept, when in fact, it is not required for the specific concept function being instantated. For this the compiler errors themselves provide the right level of protection, and the concept check would simply provide a more concise error (which doesn't benefit me since I have no problem reading the verbose template errors.) I would add it only at the end for the benefit of the library user. Thanks, Luke