Boost logo

Boost :

From: Bruno Lalande (bruno.lalande_at_[hidden])
Date: 2008-05-10 08:49:19


>> I know the principle of avoiding blob traits, as exposed in
>> Abrahams and Gurtovoy's book. But I think it doesn't apply
>> here just because the traits in question is *way* short. A
>> type, a value, an accessor.
>> And most algorithms need all of them. Does it really make
>> sense to scatter them into several metafunctions??
>
> Well, I wrote / suggested that because I have in mind a very generic set
> of concepts associated with points that would be compatible with
> libraries like CGAL.
>
> I am worried that the traits will explode becuase there are so many uses
> for a point class that have subtly different requirements. The number of
> associated types etc. in the CGAL Kernel seems to indicate that in a
> sturdy geometry library that might be the case.
>
> eg, it looks a little bit like a point concept will require a 'space'
> concept that will end up involving tons of associated types for
> compatible geometric primatives (as in the CGAL Kernel).

OK I agree with you that if the number of traits needed happens to
grow up, scattering them will be much better than having a blob traits
class. I don't know much about the CGAL kernel in its whole, I will
take a closer look.

>> I agree with Luke on this point, I'm afraid about nightmares
>> that overloading ambiguities could bring to the user.
>> However, I will consider doing a few tests to see the actual
>> consequences of what you propose.
>
> I am not talking about requiring user code to depend on ADL, I mean make
> a special 'adapted' namespace like fusion does. I foresee less problems
> with
> ::point::adapted::at_c<0>(point);
> than I do with
> point_traits<MyPoint>::template at_c<0>(point)
>
> This involves 2 parts:
> 1. _if_ the traits get to be huge, it is possible to split namespaces
> accross header files.
> 2. The annoying 'template' keyword can be a source of problems, since it
> has been my experience that some compilers require it and others dont. I
> am also concerned about the 'typename' keyword (for the same reason).
> Some traits will also probably apply to multiple concepts, and since you
> can't partially implement a traits class, you will have to mix them by
> inheritance (I think) if you want to share some traits. Then you end up
> with an issue about dependant names inherited from template base classes
> that happens on g++ and not microsoft compilers.

This is what I wanted to do to get rid of the template keyword and
take advantage of the template parameter deduction on the point type.
I wanted to merely implement it by forwarding things to the
point_traits written by the user, but maybe this approach will be
problematic (not tried yet). If it is, your approach will be a better
option, indeed. This request had already been made in another thread
so it will be done anyway.

>> >>4. Make all requirements explicit in the concept class. This
>> >> way I can look at the concept code and see what they are.
>>
>> Aren't the requirements explicit enough in the concept class
>> I've shown? If not, could you be more precise on what you'd
>> like to see more clearly specified?
>>
>> Bruno
>>
> I was worried because somebody was talking about using the traits class
> to add additional constraints. In your posted code, I dont see the
> actual definition of a traits class (I see a 'dimension_checker', and I
> see a point_traits template being used...)

Yep precisely because the concept literally says "there must exist a
specialization of point_traits with X such that this code is valid".
It's finally as much a "point traits concept" as a "point concept".
Maybe it would be better to have X being the specialized point_traits?
It would require an additional point_type typedef in the point traits
and would give something like:

template <class X> // X is a point_traits
struct PointTraits
{
  typedef typename X::coordinate_type ctype;
  enum { ccount = X::coordinate_count };

  template <int I, int Count>
  struct dimension_checker
  {
      static void check()
      {
          const typename PT::point_type* point;
          ctype coord = X::template get<I>(*point);
          typename PT::point_type* point2;
          X::template get<I>(*point2) = coord;

          dimension_checker<I+1, Count>::check();
      }
  };

  template <int Count>
  struct dimension_checker<Count, Count>
  {
      static void check() {}
  };

  BOOST_CONCEPT_USAGE(Point)
  {
      dimension_checker<0, ccount>::check();
  }
};

Then, requirements inside algorithms would be done this way:

template <class P>
BOOST_CONCEPT_REQUIRES(
   ((PointTraits<point_traits<P> >)),
   (void))
function_requiring_a_point(const P& p)
{}

It doesn't sound clearer to me though... If it's not what you were
expecting, could you propose another concept definition?

Bruno


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk