
Jeffrey Lee Hellrung, Jr. wrote:
On Sun, Nov 4, 2012 at 10:10 AM, Robert Ramey
wrote: Jeffrey Lee Hellrung, Jr. wrote:
On Sun, Nov 4, 2012 at 1:37 AM, Robert Ramey
wrote: Neil Groves wrote:
On Sat, Nov 3, 2012 at 11:29 PM, Robert Ramey
wrote:
IMHO, a strict reading of [5] does not necessitate that a concept provide ways to allow the user to create models (e.g., write archetypes).
I believe a concept definition describes those valid expressions which necessary and SUFFICIENT to define the concept. That is, I think we'll agree that any type which models the concept should support all the valid expressions list. I belive also that any type which supports all the valid expressions listed is necessarily a model of the concept. Again, would appreciate input form a concept guru here.
Is the documentation under [1] and/or [2] unclear?
It is.
Method 1 provides information I would have expected to find in the SinglePassRange concept. I'm assuming that the member functions and types would be members of any class modeling SinglePassRange. I say "assuming becaus it doesn't actually say that.
Then...why are you assuming that?
Because the documentation says they are member functions but it doesn't say of what type. One has no choice to guess or assume.
In any case, these should be part of the "valid expressions" section of the SinglePassRange concept.
*That* would be a mistake; begin/end member functions and an iterator typedef are just sufficient for a type to model SPR, but they aren't necessary. E.g., std::pair< int*, int* > is a valid range.
SinglePassRangeConcept requires the valid expression boost::begin(a) if a instance the type which models the concept. I've been directed to "method 1" of the documentation. There one is directed to implement a member begin() of some unspecified type. I'm sorry, if I want to make my own range, I just don't know what to do to from reading this.
On might think to add something like: namespace boost { template <class T> boost::range_iterator<X>::type begin(T &t){ return; } } // namespace boost
But that raises a few design questions of it's own. 1) What should go into X? 2) this will match just about anything - which will likely create other design problems.
My comments above illustrate that the description/design of the SinglePassRange concept is not comprehensible on its own. Sounds like you agree with that.
For the record, I do not.
I'm sorry I've failed to convince you, my attempt has been sincere though.
I content that it should be considered a mistake. The fact that it raises these "other questions" proves that it's a mistake. The whole idea of concepts, functional programming or whatever one want's to call it is to permit the the composition of components which can be demonstrated correct when considered one at at time.
If you have to read the whole documentation to understand one one concept - or spelunk through the code - it's a red flag that some things are coupled where they shouldn't be.
No spelunking through code is necessary, you did that on your own.
Only because I had to.
If you want to understand what you can do and how to use a concept, the concept documentation is sufficient (IMO).
Of course that's where we can't agree.
If you want to create an archetype or adapt an existing UDT to a concept, the extenstion mechanism documentation is sufficient (IMO).
To my mind, the way the "extension mechanism" is formulated is a symptom of the problem. Much of what's in there - should be part of the the SinglePassRange concept if the concept were correctly formulated.
This is also how Boost.Fusion and Boost.MPL (at least) are structured, AFAIK.
I don't think that's accurate. If you want to make your own model of a concept, you just make sure your types implement all the valid expressions.
[...snip more discussion on what belongs in the concept documentation...]
Of course this will ripple to boost::iterator_range so that we'll need template<class T> iterator_range { ... T begin(); ... };
But we already have that. So far so good.
I don't follow. What relevance does iterator_range have here, exactly?
I'm trying to demonstrate what I would expect the natural development of the library would be were it built concurrently with the documentation as I think is the best way to do it. It's meant as a constructive suggestion as to how to go about these things.
I'm sorry, I'm still not following. Can you be more concrete? I don't know what you mean by building a library "concurrently with the documentation", and I'm not sure what your suggestion about "how to go about these things" actually is.
rsd.com/blincubator.com/advice/
Sorry, not following. Are you complaining that the boost::find call compiles, and you think it shouldn't (I agree, it probably shouldn't)?
Correct.
if for some type T, BOOST_CONCEPT_ASSERT((SinglePassRangeConcept<T>)) traps then any function which requires it's parameters to model the concept SinglePassRange should also fail to compiler. This is because the implementation of f find<T> should include the statement BOOST_CONCEPT_ASSERT((SinglePassRangeConcept<T>)). I see that find<T> does in fact include this. I can't see why it traps when called directly but doesn't when called from within find. There's a mistake in the implementation somewhere - (or maybe a dumb blunder in syntax).
Hmmm, works for me, as in, it fails to compile.
-------- #include
#include #include struct X { };
namespace boost { int const * begin(X&); int const * end(X&); } // namespace boost
int main(int argc, char* argv[]) { X x; //boost::find(x, 0); // compiler error boost::range::find(x, 0); // compiler error return 0; } --------
Same error comes up as in a BOOST_CONCEPT_ASSERT, pointing to a line referencing range_const_iterator and range_mutable_iterator, suggesting that Boost.Range cannot associate an iterator type with X.
b) I thought that all the stuff was built directly in the boost namespace which I object to. I see it's really built in boost::range (much better) but hoisted up to namespace boost via a wrapper and using declaration. I have to observations about this: 1) I don't think using should every be in any header file.
Why not?
because now a user is importing a whole bunch of names into his lookup set without being informed of it.
Really, a "whole bunch"? It has a single "using range::find" that pulls boost::range::find into the boost namespace.
OK - it imports names I don't know about into my application.
How can this be any worse than defining boost::find directly in the boost namespace?
I object to that as well. But at least if I include boost::find I'm getting what I'm asking for - not some other stuff I don't know about unless I look at the library implementation.
It's actually way better this way as now boost::find will be less likely found via ADL.
Better - but not good
AFAIK, boost::find is documented, and boost::range::find is not. It's an implementation detail that, as I've said above, is no worse than defining boost::find directly in the boost namespace.
which I also object to. Robert Ramey