
On Wed, Dec 15, 2010 at 2:23 PM, Matt Calabrese <rivorus@gmail.com> wrote:
Alright, I'm updating the way concept maps are defined and I'd like some feedback here before I go through the task of creating yet another named-parameter macro. In designing Generic, I've gone in a slightly different direction from what would have been C++0x concepts and concept maps. In particular, instead of having "auto concepts", all concepts are by default explicit, however, a programmer can create one or more "auto concept maps" for a given concept. These "auto concept maps" act as concept maps with optional conditions (SFINAE and metafunction conditions).
Bump hoping that someone has feedback, positive or negative, about this approach. Also, for a while now I've been thinking about a future addition to the library that's way far off, but I'd like to hear people's opinion on it now, or at least have people thinking about it for the long while before I ever get to possibly implementing it. The idea is const-qualification for concepts, which I'll try to briefly explain. First, the motivating use-case is the "circle-ellipse" problem ( http://en.wikipedia.org/wiki/Circle-ellipse_problem ). I'm sure people are familiar with it already, but in short, a circle is a kind of ellipse, however, if an ellipse concept requires mutating operations for individual axes, then a circle can't really be considered a refinement of ellipse. Instead, the ideal solution is likely to have an Ellipse concept that doesn't have any mutating operations, and a MutableEllipse that is a refinement of Ellipse but that has mutating operations. A Circle can then be considered a refinement of Ellipse without a problem. My idea is to eventually directly support this idea via a form of const-qualification for concepts. Take the following example, in pseudo-code: ////////// concept Ellipse< T > : Regular< T > { const: // used to specify that the following are required even for const Ellipse typename value_type; value_type axis_0( T const& ); value_type axis_1( T const& ); mutable: // The following are only required for non-const Ellipse void axis_0( T&, value_type ); // set the axis length void axis_1( T&, value_type ); // set the axis length } // The above code effectively creates 2 concepts: // a "const Ellipse" concept that can view properties of the ellipse // an "Ellipse" concept that refines "const Ellipse" and that adds mutators // Now, the implementation of the Circle concept: concept Circle< T > : const Ellipse< T > // A circle meets the requirements of const Ellipse , Regular< T > // And it's also a non-const Regular type { const: value_type radius( T const& ); mutable: void radius( T&, value_type ); } ////////// There are some subtleties, but I think the above code should hopefully make some sense simply from reading it. The overall idea is that a Circle meets the requirements of const Ellipse and is also a Regular type. This should be a concise way to represent that relationship. To be a little more clear, here is what I'd imagine the above code would effectively generate: ////////// concept ConstEllipse< T > : ConstRegular< T > { typename value_type; value_type axis_0( T const& ); value_type axis_1( T const& ); } concept Ellipse< T > : ConstEllipse< T > , Regular< T > { void axis_0( T&, value_type ); // set the axis length void axis_1( T&, value_type ); // set the axis length } concept ConstCircle< T > : ConstEllipse< T > , ConstRegular< T > { value_type radius( T const& ); } concept Circle< T > : ConstCircle< T > , Regular< T > { void radius( T&, value_type ); } ////////// Notice that ConstEllipse refines ConstRegular, whereas Ellipse refines both ConstEllipse and Regular. In other words, the "constness" of a concept propagates to the concepts that it refines. I haven't shown the implementation of Regular, but it would be what you'd expect from such a concept, but with, I.E. assignment specified as mutable, similar to the mutable specifications for Ellipse. Specifically, this means that a const Regular< T > wouldn't require assignment, which is why Circle has to explicitly refine Regular< T >. In the end, I think this should be a concise way to handle situations equivalent to the circle-ellipse problem without programmers having to manually create separate mutable and immutable concepts. Have I made this point clear? If anyone has anything to say about this idea please let me know, especially anything negative. Again, if I ever pursue this idea at all, it won't be for a very long time anyway, but I'd like people to think about it now. -- -Matt Calabrese