[Concepts] Definition. Was [GSoC] [Boost.Hana] Formal review request
On Thu, 31 Jul 2014 10:54:59 -0700, Robert Ramey
Eric Niebler-4 wrote
On 07/29/2014 05:14 PM, Niall Douglas wrote:
I'm all for Concepts as in compiler enforced ones, and I'll add them to AFIO when and only when C++ gets them. But for documentation they don't help.
Wow, I couldn't disagree more. I can't imagine how the standard algorithms would be specified without the use of concepts like "RandomAccessIterator", for instance. Clustering requirements into meaningful abstractions and assigning them names makes it possible to document library interfaces without an explosion of verbosity and repetition.
+10
Usage of concepts is greatly:
a) misunderstood b) misunderestimated as to their value in design AND documentation d) The word "concepts" is a big contributor to the problem - substitute "type requirements" or "type constraints" for concepts.
-1 to the above term substitutions for concepts. Type requirements/type constrains are not concepts. The reason concepts are misunderstood is because they have not been well defined. FWIW, here's my take on how they should be defined: Concepts are sets of types whose membership are compile-time determinable. Precisely, a concept is any set expressible in the following form: { T | T is a type and p(T ...) } where p is a (n+1)-ary compile time computable boolean function (a function in the mathematical sense, not an actual C++ function). p is said to be (or to express) the type requirements or type constrains for its associated concept. (Note: just as a set membership predicate is not its set, a type requirement is not its concept. For example, the predicate "there exists a,b and a,b are integers and b != 0 and c = a/b" does not denote the set of rational numbers, the symbol Q does.) A type T is said to model a concept C if T is a member of C. In such a case we also say that "T is a C". A concept B is said to be a refinement of a concept A if B is a subset of A. Why use concepts? Because they are helpful in documenting generic code, especially template type parameter requirements. Examples: 1) DefaultConstructible := { T | T has the method "T()" defined and accessible. } // Requirements: // T is DefaultConstructible. template <typename T> struct FooBar { ... }; std::tuple<int> is DefaultConstructible, therefore FooBar< std::tuple<int> > is well formed. Mostafa
On 2014-08-04 13:32, Mostafa wrote:
On Thu, 31 Jul 2014 10:54:59 -0700, Robert Ramey
wrote: Eric Niebler-4 wrote
On 07/29/2014 05:14 PM, Niall Douglas wrote:
I'm all for Concepts as in compiler enforced ones, and I'll add them to AFIO when and only when C++ gets them. But for documentation they don't help.
Wow, I couldn't disagree more. I can't imagine how the standard algorithms would be specified without the use of concepts like "RandomAccessIterator", for instance. Clustering requirements into meaningful abstractions and assigning them names makes it possible to document library interfaces without an explosion of verbosity and repetition.
+10
Usage of concepts is greatly:
a) misunderstood b) misunderestimated as to their value in design AND documentation d) The word "concepts" is a big contributor to the problem - substitute "type requirements" or "type constraints" for concepts.
-1 to the above term substitutions for concepts. Type requirements/type constrains are not concepts. The reason concepts are misunderstood is because they have not been well defined. FWIW, here's my take on how they should be defined:
Concepts are sets of types whose membership are compile-time determinable. I think you are mistaken. A concept is a set of requirements, not a set of types that fullfill these requirements.
This also reflects the normal meaning of the word concept, see for instance http://www.oxforddictionaries.com/definition/english/concept
On Mon, 04 Aug 2014 08:39:36 -0700, Roland Bock
On 2014-08-04 13:32, Mostafa wrote:
On Thu, 31 Jul 2014 10:54:59 -0700, Robert Ramey
wrote: Eric Niebler-4 wrote
On 07/29/2014 05:14 PM, Niall Douglas wrote:
I'm all for Concepts as in compiler enforced ones, and I'll add them to AFIO when and only when C++ gets them. But for documentation they don't help.
Wow, I couldn't disagree more. I can't imagine how the standard algorithms would be specified without the use of concepts like "RandomAccessIterator", for instance. Clustering requirements into meaningful abstractions and assigning them names makes it possible to document library interfaces without an explosion of verbosity and repetition.
+10
Usage of concepts is greatly:
a) misunderstood b) misunderestimated as to their value in design AND documentation d) The word "concepts" is a big contributor to the problem - substitute "type requirements" or "type constraints" for concepts.
-1 to the above term substitutions for concepts. Type requirements/type constrains are not concepts. The reason concepts are misunderstood is because they have not been well defined. FWIW, here's my take on how they should be defined:
Concepts are sets of types whose membership are compile-time determinable. I think you are mistaken. A concept is a set of requirements, not a set of types that fullfill these requirements.
I understand that some may have a problem with such a definition because it does not have an immediate programmatic counterpart. That is we can only implement concept checks, hence Boost.ConceptChecks, and not concepts themselves in C++. But I view concepts not as a programmatic tool but as a communication tool for conveying programmer intent. The main reason I hold this view is because it's easier to think in terms of sets of types than in terms of sets of type requirements. For example, ShapeConcept := { T | T has the method "void display() const" defined } TriangleConcept := { T | T models Shape and T has the following methods defined: "Edge edgeOne()", "Edge edgeTwo()", "Edge edgeThree()" } // T models ShapeConcept template <typename T> void Display(T & t); It's obvious that if U models a TriangleConcept then Display(u) for an object u of type U is well-formed. (That's because TriangleConcept is a subset of ShapeConcept and U is a member of the latter.) Note that this is similar to the relationship between types and objects. Conceptually types are sets of objects and a subtype contains a subset of the objects of its supertype. Now, let's try reworking the above example in terms of sets of type requirements instead. The TriangleConcept then is a refinement of ShapeConcept if the TriangleConcept is a superset of the ShapeConcept. But that's counter-intuitive because the number of types that satisfy the TriangleConcept is less than the number of types that satisfy ShapeConcept. Additionally, if concepts were sets of type requirements than the phrase "T is DefaultConstructible" reads awkwardly, it almost sounds as if T were a type requirement itself, when we actually mean to say that T satisfies the requirements of default constructibility. And the language "x satisfies abc" usually connotates set membership.
This also reflects the normal meaning of the word concept, see for instance
http://www.oxforddictionaries.com/definition/english/concept
??? From the above link: "1.4 Philosophy An idea or mental image which corresponds to some distinct entity or class of entities, or to its essential features, or determines the application of a term (especially a predicate), and thus plays a part in the use of reason or language." Mostafa
On 2014-08-05 02:08, Mostafa wrote:
On Mon, 04 Aug 2014 08:39:36 -0700, Roland Bock
wrote: On 2014-08-04 13:32, Mostafa wrote:
On Thu, 31 Jul 2014 10:54:59 -0700, Robert Ramey
wrote: Eric Niebler-4 wrote
On 07/29/2014 05:14 PM, Niall Douglas wrote:
I'm all for Concepts as in compiler enforced ones, and I'll add them to AFIO when and only when C++ gets them. But for documentation they don't help.
Wow, I couldn't disagree more. I can't imagine how the standard algorithms would be specified without the use of concepts like "RandomAccessIterator", for instance. Clustering requirements into meaningful abstractions and assigning them names makes it possible to document library interfaces without an explosion of verbosity and repetition.
+10
Usage of concepts is greatly:
a) misunderstood b) misunderestimated as to their value in design AND documentation d) The word "concepts" is a big contributor to the problem - substitute "type requirements" or "type constraints" for concepts.
-1 to the above term substitutions for concepts. Type requirements/type constrains are not concepts. The reason concepts are misunderstood is because they have not been well defined. FWIW, here's my take on how they should be defined:
Concepts are sets of types whose membership are compile-time determinable. I think you are mistaken. A concept is a set of requirements, not a set of types that fullfill these requirements.
I understand that some may have a problem with such a definition because it does not have an immediate programmatic counterpart. That is we can only implement concept checks, hence Boost.ConceptChecks, and not concepts themselves in C++. But I view concepts not as a programmatic tool but as a communication tool for conveying programmer intent.
The main reason I hold this view is because it's easier to think in terms of sets of types than in terms of sets of type requirements. That's not an argument IMHO. Even if a concept C is a set of requirements, you can think of the set of types that meet these requirements, lets call them T(C).
Then for two concepts A and B, we call A a refinement of B if T(A) is a subset of T(B). So you can still express everything you want to express and the concept is what we write in code: A set of requirements. <snip>
Now, let's try reworking the above example in terms of sets of type requirements instead. The TriangleConcept then is a refinement of ShapeConcept if the TriangleConcept is a superset of the ShapeConcept. But that's counter-intuitive because the number of types that satisfy the TriangleConcept is less than the number of types that satisfy ShapeConcept.
See above. And sure, if concept A is a superset of concept B, then T(A) is a subset of T(B). There is nothing counter-intuitive about that afaict.
Additionally, if concepts were sets of type requirements than the phrase "T is DefaultConstructible" reads awkwardly, it almost sounds as if T were a type requirement itself, when we actually mean to say that T satisfies the requirements of default constructibility. And the language "x satisfies abc" usually connotates set membership.
This also reflects the normal meaning of the word concept, see for instance
http://www.oxforddictionaries.com/definition/english/concept
??? From the above link: "1.4 Philosophy An idea or mental image which corresponds to some distinct entity or class of entities, or to its essential features, or determines the application of a term (especially a predicate), and thus plays a part in the use of reason or language." In short (and probably not precise enough since I am not a philosopher), a concept is not a thing (aka type in template programming) or set of
Sure, that type is a member of T(DefaultConstructible). I don't get your argument at all. If you say "this car is green", you say both "this car is a member of the set of green things" and "this car meets the requirements of being green". It does neither imply that "green is the set of green things" (endless recursion) nor does it say that "green is a set of being-green-requirements" (also endless recursion). Still, everyone knows what is meant without feeling awkward about it. So why not use the term concept in a way that matches what we actually do in code? things, it is an idea about it or its essential features, for instance a predicate. Regards, Roland
On Tue, 05 Aug 2014 00:07:42 -0700, Roland Bock
On 2014-08-05 02:08, Mostafa wrote:
On Mon, 04 Aug 2014 08:39:36 -0700, Roland Bock
wrote:
[snip]
Additionally, if concepts were sets of type requirements than the phrase "T is DefaultConstructible" reads awkwardly, it almost sounds as if T were a type requirement itself, when we actually mean to say that T satisfies the requirements of default constructibility. And the language "x satisfies abc" usually connotates set membership. Sure, that type is a member of T(DefaultConstructible).
I don't get your argument at all. If you say "this car is green", you say both "this car is a member of the set of green things" and "this car meets the requirements of being green". It does neither imply that "green is the set of green things" (endless recursion) nor does it say that "green is a set of being-green-requirements" (also endless recursion). Still, everyone knows what is meant without feeling awkward about it.
Unfortunately English can be ambiguous, so let's be more precise. When one says "this car is green" one actually means "this car is a green thing" (green is being used as a noun, not as an adjective like "green balloon"). That means "this car is a member of GreenThings". If GreenThings were a set of requirements then that means "this car" is also a requirement, which obviously it's not. Therefore GreenThings, the concept in this discussion, is a set of objects that satisfy the requirement of being green.
So why not use the term concept in a way that matches what we actually do in code?
Because that's a narrow and implementation-dependent point of view. When we introduce people to classes, hopefully we don't first define them to be some set of rules for determining the layout of a region of memory, rather we define them to be nouns; that is it's a communication tool for expressing programmer intent. By thinking about classes abstractly, we are able to more easily reason with them, like how UML robustness diagrams can be used to discover classes and the relationships between them. FWIW, it might interest you to read this blog on concepts by Bartosz Milewski: http://bartoszmilewski.com/2010/06/24/c-concepts-a-postmortem/ (Disclaimer: he holds my position and terms your definition "constrained templates", but his posting is informative in comparing our approaches.) Mostafa
On 2014-08-05 12:13, Mostafa wrote:
On Tue, 05 Aug 2014 00:07:42 -0700, Roland Bock
wrote: On 2014-08-05 02:08, Mostafa wrote:
On Mon, 04 Aug 2014 08:39:36 -0700, Roland Bock
wrote: [snip]
Additionally, if concepts were sets of type requirements than the phrase "T is DefaultConstructible" reads awkwardly, it almost sounds as if T were a type requirement itself, when we actually mean to say that T satisfies the requirements of default constructibility. And the language "x satisfies abc" usually connotates set membership. Sure, that type is a member of T(DefaultConstructible).
I don't get your argument at all. If you say "this car is green", you say both "this car is a member of the set of green things" and "this car meets the requirements of being green". It does neither imply that "green is the set of green things" (endless recursion) nor does it say that "green is a set of being-green-requirements" (also endless recursion). Still, everyone knows what is meant without feeling awkward about it.
Unfortunately English can be ambiguous, so let's be more precise. When one says "this car is green" one actually means "this car is a green thing" (green is being used as a noun, not as an adjective like "green balloon"). That means "this car is a member of GreenThings". If GreenThings were a set of requirements then that means "this car" is also a requirement, which obviously it's not.
You're only ever seeing your view :-) Another option is: When one says "this car is green", one actually means "this car emits light with a wavelength around 510nm". So the concept "green" is not a set of green things, it is a set of requirements (in this case with one element, namely "emits light with a wavelength around 510nm"). Since both views are equally possible, I'd stick with the one closer to practice.
Therefore GreenThings, the concept in this discussion, is a set of objects that satisfy the requirement of being green.
So why not use the term concept in a way that matches what we actually do in code?
Because that's a narrow and implementation-dependent point of view.
I did not write "concepts are pieces of code"...
When we introduce people to classes, hopefully we don't first define them to be some set of rules for determining the layout of a region of memory, rather we define them to be nouns; that is it's a communication tool for expressing programmer intent. By thinking about classes abstractly, we are able to more easily reason with them, like how UML robustness diagrams can be used to discover classes and the relationships between them.
FWIW, it might interest you to read this blog on concepts by Bartosz Milewski: http://bartoszmilewski.com/2010/06/24/c-concepts-a-postmortem/ (Disclaimer: he holds my position and terms your definition "constrained templates", but his posting is informative in comparing our approaches.) I read that one before, but thanks for the reminder :-)
Afaict, your view is in line with what he calls concept maps. Anyway, this has gone far too long already, I am out of here. Best, Roland
On Tue, 05 Aug 2014 04:58:35 -0700, Roland Bock
On 2014-08-05 12:13, Mostafa wrote:
On Tue, 05 Aug 2014 00:07:42 -0700, Roland Bock
wrote: On 2014-08-05 02:08, Mostafa wrote:
On Mon, 04 Aug 2014 08:39:36 -0700, Roland Bock
wrote: [snip]
Additionally, if concepts were sets of type requirements than the phrase "T is DefaultConstructible" reads awkwardly, it almost sounds as if T were a type requirement itself, when we actually mean to say that T satisfies the requirements of default constructibility. And the language "x satisfies abc" usually connotates set membership. Sure, that type is a member of T(DefaultConstructible).
I don't get your argument at all. If you say "this car is green", you say both "this car is a member of the set of green things" and "this car meets the requirements of being green". It does neither imply that "green is the set of green things" (endless recursion) nor does it say that "green is a set of being-green-requirements" (also endless recursion). Still, everyone knows what is meant without feeling awkward about it.
Unfortunately English can be ambiguous, so let's be more precise. When one says "this car is green" one actually means "this car is a green thing" (green is being used as a noun, not as an adjective like "green balloon"). That means "this car is a member of GreenThings". If GreenThings were a set of requirements then that means "this car" is also a requirement, which obviously it's not.
You're only ever seeing your view :-) Another option is: When one says "this car is green", one actually means "this car emits light with a wavelength around 510nm". So the concept "green" is not a set of green things, it is a set of requirements (in this case with one element, namely "emits light with a wavelength around 510nm").
No, I see your pov, I just claim you're view is logically flawed. I find this topic interesting, so if I may, I shall try to prove the flaw. 1) I claim that when one says "this car is green" one means "this car is a green thing", that's because by the rules of English syntax "green" in the original sentence has to be a noun, and because "green" is neither a person nor a place, it must be a thing. 2) So the question becomes what is a "green thing"? I claim that a "green thing" is any thing that satisfies being "green". 3) Let's assume for the sake of argument that "green" is a set of requirements. What is a requirement? It's a logical predicate, which is itself a boolean-valued function. So the "green" concept can be defined as follows: green := { p = { (x, p(x)) | p(x) = "does x emit light at ...} } 4) How does a thing satisfy being "green"? Since "green" is a set, the thing in question satisfies being "green" by being a member of that set. Since "green" as defined above has only one member, the thing in question satisfies being "green" by being the predicate p. 5) Hence, a green thing can only be the predicate p and, ergo, the car is the predicate p. 6) Reductio ad absurdum. Our intent was not to say that the car is the predicate p, rather that the car was a truth value for p, that is it satisfied the predicate/requirement p. Hence my original assertion that the English construct "T is DefaultConstructible" reads awkwardly if DefaultConstructible is defined as a set of requirements. (Note, I'll tried to do was symbolize in the language of logic and set theory the sentence "this car is green", or "T is DefaultConstructible".) Mostafa
On 2014-08-05 15:17, Mostafa wrote:
On Tue, 05 Aug 2014 04:58:35 -0700, Roland Bock
wrote: On 2014-08-05 12:13, Mostafa wrote:
On Tue, 05 Aug 2014 00:07:42 -0700, Roland Bock
wrote: On 2014-08-05 02:08, Mostafa wrote:
On Mon, 04 Aug 2014 08:39:36 -0700, Roland Bock
wrote: [snip]
Additionally, if concepts were sets of type requirements than the phrase "T is DefaultConstructible" reads awkwardly, it almost sounds as if T were a type requirement itself, when we actually mean to say that T satisfies the requirements of default constructibility. And the language "x satisfies abc" usually connotates set membership. Sure, that type is a member of T(DefaultConstructible).
I don't get your argument at all. If you say "this car is green", you say both "this car is a member of the set of green things" and "this car meets the requirements of being green". It does neither imply that "green is the set of green things" (endless recursion) nor does it say that "green is a set of being-green-requirements" (also endless recursion). Still, everyone knows what is meant without feeling awkward about it.
Unfortunately English can be ambiguous, so let's be more precise. When one says "this car is green" one actually means "this car is a green thing" (green is being used as a noun, not as an adjective like "green balloon"). That means "this car is a member of GreenThings". If GreenThings were a set of requirements then that means "this car" is also a requirement, which obviously it's not.
You're only ever seeing your view :-) Another option is: When one says "this car is green", one actually means "this car emits light with a wavelength around 510nm". So the concept "green" is not a set of green things, it is a set of requirements (in this case with one element, namely "emits light with a wavelength around 510nm").
No, I see your pov, I just claim you're view is logically flawed. I find this topic interesting, so if I may, I shall try to prove the flaw. I find it interesting, too, so OK, here goes again.
1) I claim that when one says "this car is green" one means "this car is a green thing", that's because by the rules of English syntax "green" in the original sentence has to be a noun
I am not a native english speaker, but I am pretty sure that "green" is an adjective, which is not a noun. It is something that describes a noun.
, and because "green" is neither a person nor a place, it must be a thing. 2) So the question becomes what is a "green thing"? I claim that a "green thing" is any thing that satisfies being "green". 3) Let's assume for the sake of argument that "green" is a set of requirements. What is a requirement? It's a logical predicate, which is itself a boolean-valued function. So the "green" concept can be defined as follows: green := { p = { (x, p(x)) | p(x) = "does x emit light at ...} }
4) How does a thing satisfy being "green"? Since "green" is a set, the thing in question satisfies being "green" by being a member of that set.
Well, I say there's your flaw. You claim that "a is b" automatically means "a is a member of b" if b is a set. I am pretty sure that's not backed by anything, not even math. I'll try to illustrate with a more common example. "x is rational" means two things a) "x is a member of the set of rational numbers, called R" b) "x meets the requirement that there are natural numbers a and b!=0 such that x = a/b" Note that rational != R. rational is a predicate expressing a) and b). Translating it to "this car is green": green is neither the set of green things nor the set of requirements. It is a predicate that can express set membership and/or met requirements. Now, when we say "T is DefaultConstructible" and DefaultConstructible is a concept, neither your nor my view of concept fits directly since neither one is a predicate. I therefore think that it is question of convention whether this means a) T is one of the types of DefaultConstructible b) T meets the requirements of DefaultConstructible And if it is just a question of convention, you know my preference. And see Robert's post and my reply to it, too. Regards, Roland
On Tue, 05 Aug 2014 09:38:02 -0700, Roland Bock
On 2014-08-05 15:17, Mostafa wrote:
On Tue, 05 Aug 2014 04:58:35 -0700, Roland Bock
wrote: On 2014-08-05 12:13, Mostafa wrote:
On Tue, 05 Aug 2014 00:07:42 -0700, Roland Bock
wrote: On 2014-08-05 02:08, Mostafa wrote:
On Mon, 04 Aug 2014 08:39:36 -0700, Roland Bock
wrote: [snip]
Additionally, if concepts were sets of type requirements than the phrase "T is DefaultConstructible" reads awkwardly, it almost sounds as if T were a type requirement itself, when we actually mean to say that T satisfies the requirements of default constructibility. And the language "x satisfies abc" usually connotates set membership. Sure, that type is a member of T(DefaultConstructible).
I don't get your argument at all. If you say "this car is green", you say both "this car is a member of the set of green things" and "this car meets the requirements of being green". It does neither imply that "green is the set of green things" (endless recursion) nor does it say that "green is a set of being-green-requirements" (also endless recursion). Still, everyone knows what is meant without feeling awkward about it.
Unfortunately English can be ambiguous, so let's be more precise. When one says "this car is green" one actually means "this car is a green thing" (green is being used as a noun, not as an adjective like "green balloon"). That means "this car is a member of GreenThings". If GreenThings were a set of requirements then that means "this car" is also a requirement, which obviously it's not.
You're only ever seeing your view :-) Another option is: When one says "this car is green", one actually means "this car emits light with a wavelength around 510nm". So the concept "green" is not a set of green things, it is a set of requirements (in this case with one element, namely "emits light with a wavelength around 510nm").
No, I see your pov, I just claim you're view is logically flawed. I find this topic interesting, so if I may, I shall try to prove the flaw. I find it interesting, too, so OK, here goes again.
1) I claim that when one says "this car is green" one means "this car is a green thing", that's because by the rules of English syntax "green" in the original sentence has to be a noun
I am not a native english speaker, but I am pretty sure that "green" is an adjective, which is not a noun. It is something that describes a noun.
Green is both an adjective and a noun. Context is used to disambiguate its state. I claim that the sentence "x is y" implies y is a noun whenever x is a noun.
, and because "green" is neither a person nor a place, it must be a thing. 2) So the question becomes what is a "green thing"? I claim that a "green thing" is any thing that satisfies being "green". 3) Let's assume for the sake of argument that "green" is a set of requirements. What is a requirement? It's a logical predicate, which is itself a boolean-valued function. So the "green" concept can be defined as follows: green := { p = { (x, p(x)) | p(x) = "does x emit light at ...} }
4) How does a thing satisfy being "green"? Since "green" is a set, the thing in question satisfies being "green" by being a member of that set.
Well, I say there's your flaw. You claim that "a is b" automatically means "a is a member of b" if b is a set. I am pretty sure that's not backed by anything, not even math.
I take as my justification the existing convention regarding types and objects. Take the following classes: class Triangle {...}; class Square {...}; I claim that Triangle, Square, or any class for that matter, defines some set of objects. Now when we declare: Triangle x; we say "x is a Triangle"; and by that we actually mean x is a member of the set Triangle.
On 05/08/2014, at 11:17 PM, Mostafa
1) I claim that when one says "this car is green" one means "this car is a green thing", that's because by the rules of English syntax "green" in the original sentence has to be a noun,
"Green" is an adjective in that sentence. See the examples at http://www.perfectyourenglish.com/grammar/predicative-position.htm
On 5/08/2014 1:39 AM, Roland Bock wrote:
On 2014-08-04 13:32, Mostafa wrote:
Concepts are sets of types I think you are mistaken. A concept is a set of requirements,
I am under a New Year's resolution not to start philosophical arguments, but this one has already begun, so ... It may be helpful to consider this principle about sets: set A and set B are the same set whenever all the elements of A are elements of B and all the elements of B are elements of A. Or in symbols: (A = B) iff (forall x)(x in A iff x in B) (Standard example: The set of equilateral triangles and the set of equiangular triangles are the same set, because all equilateral triangles are equiangular and vice versa.) So Mostafa's statement (above) commits him to this: Concept A and concept B are the same concept whenever all the types in A are in B, and all the types in B are in A. And Roland's statement commits him to this: Concept A and concept B are the same concept whenever all the requirements in A are in B, and all the requirements in B are in A. I think this means that Roland will be able to discriminate concepts more finely than Mostafa can. Now, whether that is an advantage or a disadvantage, I leave for you gentlemen to discuss. :) --- Michael
2014-08-05 6:33 GMT+02:00 Michael Shepanski
On 5/08/2014 1:39 AM, Roland Bock wrote:
On 2014-08-04 13:32, Mostafa wrote:
Concepts are sets of types
I think you are mistaken. A concept is a set of requirements,
I am under a New Year's resolution not to start philosophical arguments, but this one has already begun, so ...
Please don't forget, that not all requirements can be checked at compile time. For example: TotallyOrdered. Just by checking, that an expression (a
On 2014-08-05 10:30, Krzysztof Czainski wrote:
2014-08-05 6:33 GMT+02:00 Michael Shepanski
: On 5/08/2014 1:39 AM, Roland Bock wrote:
On 2014-08-04 13:32, Mostafa wrote:
Concepts are sets of types
I think you are mistaken. A concept is a set of requirements,
I am under a New Year's resolution not to start philosophical arguments, but this one has already begun, so ...
Please don't forget, that not all requirements can be checked at compile time. For example: TotallyOrdered. Just by checking, that an expression (a
So, while I think it doesn't matter, whether we view concepts as sets of types or requirements Well, if you consider TotallyOrdered a concept, then by this reasoning, it cannot be a set of types. But it could be a set of requirements :-)
I admit that in this context I haven't thought of concepts that cannot be verified at compile time. Thanks for the hint!
, I'd like to support this sentence of Mostafa: "I view concepts not as a programmatic tool but as a communication tool for conveying programmer intent."
I think it is both, a programmatic tool and a communication tool. Cheers, Roland
On Tue, 05 Aug 2014 01:59:34 -0700, Roland Bock
On 2014-08-05 10:30, Krzysztof Czainski wrote:
2014-08-05 6:33 GMT+02:00 Michael Shepanski
: On 5/08/2014 1:39 AM, Roland Bock wrote:
On 2014-08-04 13:32, Mostafa wrote:
Concepts are sets of types
I think you are mistaken. A concept is a set of requirements,
I am under a New Year's resolution not to start philosophical arguments, but this one has already begun, so ...
Please don't forget, that not all requirements can be checked at compile time. For example: TotallyOrdered. Just by checking, that an expression (a
So, while I think it doesn't matter, whether we view concepts as sets of types or requirements Well, if you consider TotallyOrdered a concept, then by this reasoning, it cannot be a set of types. But it could be a set of requirements :-)
Yes it can. TotallyOrdered := { T | if a,b,c are objects of T then ... }
On 2014-08-05 12:14, Mostafa wrote:
On Tue, 05 Aug 2014 01:59:34 -0700, Roland Bock
wrote: On 2014-08-05 10:30, Krzysztof Czainski wrote:
2014-08-05 6:33 GMT+02:00 Michael Shepanski
: On 5/08/2014 1:39 AM, Roland Bock wrote:
On 2014-08-04 13:32, Mostafa wrote:
Concepts are sets of types
I think you are mistaken. A concept is a set of requirements,
I am under a New Year's resolution not to start philosophical arguments, but this one has already begun, so ...
Please don't forget, that not all requirements can be checked at compile time. For example: TotallyOrdered. Just by checking, that an expression (a
So, while I think it doesn't matter, whether we view concepts as sets of types or requirements Well, if you consider TotallyOrdered a concept, then by this reasoning, it cannot be a set of types. But it could be a set of requirements :-)
Yes it can. TotallyOrdered := { T | if a,b,c are objects of T then ... }
As Kris pointed out: Whether an object is TotallyOrdered or not cannot be checked at compile time because it does not depend on the type alone, it also depends on runtime information. Hence, not a set of types. Best, Roland
On Tue, 05 Aug 2014 04:27:31 -0700, Roland Bock
On 2014-08-05 12:14, Mostafa wrote:
On Tue, 05 Aug 2014 01:59:34 -0700, Roland Bock
wrote: On 2014-08-05 10:30, Krzysztof Czainski wrote:
2014-08-05 6:33 GMT+02:00 Michael Shepanski
: On 5/08/2014 1:39 AM, Roland Bock wrote:
On 2014-08-04 13:32, Mostafa wrote:
> Concepts are sets of types > I think you are mistaken. A concept is a set of requirements,
I am under a New Year's resolution not to start philosophical arguments, but this one has already begun, so ...
Please don't forget, that not all requirements can be checked at compile time. For example: TotallyOrdered. Just by checking, that an expression (a
So, while I think it doesn't matter, whether we view concepts as sets of types or requirements Well, if you consider TotallyOrdered a concept, then by this reasoning, it cannot be a set of types. But it could be a set of requirements :-)
Yes it can. TotallyOrdered := { T | if a,b,c are objects of T then ... }
As Kris pointed out: Whether an object is TotallyOrdered or not cannot be checked at compile time because it does not depend on the type alone, it also depends on runtime information. Hence, not a set of types.
That's irrelevant. My original definition of concepts can easily be expanded to remove the compile time determinability restriction. Then, TotallyOrdered as a set of types does conceptually exist, and can be effectively used as a documentation tool. The concept TotallyOrdered may not depend on the *static* information of the type, but it sure does depend on objects of the type, and, ergo, it depends on the type.
On 2014-08-05 13:48, Mostafa wrote:
On Tue, 05 Aug 2014 04:27:31 -0700, Roland Bock
wrote: On 2014-08-05 12:14, Mostafa wrote:
On Tue, 05 Aug 2014 01:59:34 -0700, Roland Bock
wrote: On 2014-08-05 10:30, Krzysztof Czainski wrote:
2014-08-05 6:33 GMT+02:00 Michael Shepanski
: On 5/08/2014 1:39 AM, Roland Bock wrote:
> On 2014-08-04 13:32, Mostafa wrote: > >> Concepts are sets of types >> > I think you are mistaken. A concept is a set of requirements, > I am under a New Year's resolution not to start philosophical arguments, but this one has already begun, so ...
Please don't forget, that not all requirements can be checked at compile time. For example: TotallyOrdered. Just by checking, that an expression (a
So, while I think it doesn't matter, whether we view concepts as sets of types or requirements Well, if you consider TotallyOrdered a concept, then by this reasoning, it cannot be a set of types. But it could be a set of requirements :-)
Yes it can. TotallyOrdered := { T | if a,b,c are objects of T then ... }
As Kris pointed out: Whether an object is TotallyOrdered or not cannot be checked at compile time because it does not depend on the type alone, it also depends on runtime information. Hence, not a set of types.
That's irrelevant. My original definition of concepts can easily be expanded to remove the compile time determinability restriction. Then, TotallyOrdered as a set of types does conceptually exist, and can be effectively used as a documentation tool. The concept TotallyOrdered may not depend on the *static* information of the type, but it sure does depend on objects of the type, and, ergo, it depends on the type.
It depends on properties of the type/object. That's what requirements are for. Anyway, sorry, I can't continue here. See you in another thread :-)
Please don't forget, that not all requirements can be checked at compile time. For example: TotallyOrdered. Just by checking, that an expression (a This is not true. requirements are on types - not on instantiations of types. If it can't be checked at compile time - it's not a type requirement - it's something else (perhaps a pre-condition). TotallyOrdered doesn't refer to some container that may or may not be sorted. It refers to the existent of a comparison function for the type which fulfills a number of requirements. To see this look at https://www.sgi.com/tech/stl/StrictWeakOrdering.html Here we can specify type requirements on functions which provide for a strict weak ordering. These can all be verified at compile time based on the properties of the types. Note that not all can be verified by the compiler as some depend upon the semantic definition of the function. But one doesn't have to know that runtime data to verify that the function meets the conditions for a strict weak ordering. To summarize - all type requirements can be verified when the code is written - but not all type requirements can be verified automatically by the compiler. So verification of by the compiler isn't perfectly exhaustive - but it's a heck of a lot better than what we usually do - which is nothing. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
2014-08-05 17:42 GMT+02:00 Robert Ramey
Please don't forget, that not all requirements can be checked at compile time. For example: TotallyOrdered. Just by checking, that an expression (a
</quote>
This is not true.
requirements are on types - not on instantiations of types. If it can't be checked at compile time - it's not a type requirement - it's something else (perhaps a pre-condition).
TotallyOrdered doesn't refer to some container that may or may not be sorted. It refers to the existent of a comparison function for the type which fulfills a number of requirements. To see this look at https://www.sgi.com/tech/stl/StrictWeakOrdering.html
Here we can specify type requirements on functions which provide for a strict weak ordering. These can all be verified at compile time based on the properties of the types. Note that not all can be verified by the compiler as some depend upon the semantic definition of the function. But one doesn't have to know that runtime data to verify that the function meets the conditions for a strict weak ordering. To summarize - all type requirements can be verified when the code is written - but not all type requirements can be verified automatically by the compiler.
So verification of by the compiler isn't perfectly exhaustive - but it's a heck of a lot better than what we usually do - which is nothing.
Robert Ramey
What about this example: struct Circ { unsigned x; explicit Circ(unsigned i=0) : x(i%256) {} }; bool operator<(Circ a, Circ b) { return (b.x-a.x)%256 < (a.x-b.x)%256; } Is std::set<Circ> valid? I think generally not, but... suppose that we know, that we're only going to use values 0-127. In this case std::set<Circ> is valid. Regards, Kris
Krzysztof Czainski wrote
What about this example:
struct Circ { unsigned x; explicit Circ(unsigned i=0) : x(i%256) {} }; bool operator<(Circ a, Circ b) { return (b.x-a.x)%256 < (a.x-b.x)%256; }
Is std::set <Circ> valid?
I think generally not, but... suppose that we know, that we're only going to use values 0-127. In this case std::set <Circ> is valid.
it won't trap at compile time. Of course depending upon the value of x it might not be valid at runtime - but "type requirements" don't pretend to address that. Type requirements specify what types are permitted at for template parameters - no more no less. It can't guarantee that any particular instance is "valid" (whatever that might mean). Runtime checking is a job of "pre-conditions" and assert. But if you want - you "could" go a little overboard and use template<int X> struct Circ { static unsigned x = X; }; bool operator<(Circ a, Circ b) { return (b.x-a.x)%256 < (a.x-b.x)%256; } Of course this is outside the scope of "type requirements" but it's still interesting. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
I believe that "C++ Concept" was originally defined by the following web page or writing contemporary to it. https://www.sgi.com/tech/stl/stl_introduction.html . A relevent quote is "One very important question to ask about any template function, not just about STL algorithms, is what the set of types is that may correctly be substituted for the formal template parameters. Clearly, for example, int* or double* may be substituted for find's formal template parameter InputIterator. " I don't think we want to alter this definition. It's not formal (in the mathematical sense), but it's not ambiguous in our context. My complaint isn't the definition - it's the phrase/word that was chosen to embody the idea. The word chosen was "Concepts" which, in my view has led to all sorts of confusion to the casual reader - as most of are when we read documentation. So my view is that we would be better served by using the term "type requirements" and/or "type constraints" rather than the word "Concepts". That's all. Of course people can and will continue to use the word "Concept" in the way they have been. But that doesn't prohibit me from using the phrase "type constraint" from referring to the original idea. It's somewhat off topic, but I'm going to take the opportunity to point out https://www.sgi.com/tech/stl/doc_introduction.html . I've come to believe that C++ libraries - in particular parameterized types, are best described by the documentation approach embodied in this link. It is sufficiently formal where it has to be - but not so formal that one gets too bogged down. I've made a big point of this inhttp://rrsd.com/blincubator.com/requirements_documentation/ . My criticism of the HANA documentation is really that it fails to follow this format and content. One of the objections raised to my criticism is that this form of documentation is in some sense not modern, specific to STL, or in some way not a good model for all C++ libraries. It is this idea which I reject - totally. Library authors would be best served by producing this form of documentation (concurrently with code) and not spend any time re-inventing their own documentation form. Use this one and spend your time on coding! Another interesting quote is: "Concepts are not a part of the C++ language; there is no way to declare a concept in a program, or to declare that a particular type is a model of a concept. " But today we have the boost concept library which while it doesn't make concepts part of the language itself provides a library which permits type requirements to be specified as part of the code and checked at compile time. But with C++11 it's much more interesting. I just came upon: http://en.cppreference.com/w/cpp/concept which echoes my views on the whole subject. I don't have the C++11 spec - but I'm assuming/hoping that these type requirements are part of it. This section only defines the named type requirements. But wait!!!! there's more !!! For A good number of the concepts - example DefaultConstructable http://en.cppreference.com/w/cpp/concept/DefaultConstructible -there exists a constexpr function such as http://en.cppreference.com/w/cpp/types/is_default_constructible . So in this case we DO have concepts built into the language (libraries). Making a concept checking class would be as simple is: template<class T> struct DefaultConstructible { static_assert(std::is_default_constructible<T>::value, "Class is not default constructible"); }; Making a new concept class is pretty simple - leave as an excursive for the reader But wait - there's even more!!!! if there were a type trait defined for each concept - we would have type dispatching based on named type requirements - example std::enable_ifstd::is_default_constructible<T> void f(const T &t); So f would be declared for a type T if and only if T were DefaultConstructible. Basically, this implements most of the functionality in Boost Concept Checking and also Concepts Lite today - and in a way which dovetails with what is (in my view) the preferred documentation approach. It makes for a coherent and complete system from coding to documentation. Since most of this is "form filling" it's easy, mechanical and almost guaranteed to be correct. This is the direction we (Boost and all of C++) need to go. That is, we've known what to do for some time we just have to start doing more. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
Hi Robert, Focussing on the term "concept" below. I'll comment on some of the other parts later. On 2014-08-05 17:29, Robert Ramey wrote:
I believe that "C++ Concept" was originally defined by the following web page or writing contemporary to it. https://www.sgi.com/tech/stl/stl_introduction.html . A relevent quote is
"One very important question to ask about any template function, not just about STL algorithms, is what the set of types is that may correctly be substituted for the formal template parameters. Clearly, for example, int* or double* may be substituted for find's formal template parameter InputIterator. " Thanks for providing this link!
Citing from it: "we call such a set of type requirements a /concept. [...] //We say that a type /conforms to a concept/, or that it /is a model of a concept/, if it satisfies all of those requirements"/.
I don't think we want to alter this definition. It's not formal (in the mathematical sense), but it's not ambiguous in our context.
My complaint isn't the definition - it's the phrase/word that was chosen to embody the idea. The word chosen was "Concepts" which, in my view has led to all sorts of confusion to the casual reader - as most of are when we read documentation. So my view is that we would be better served by using the term "type requirements" and/or "type constraints" rather than the word "Concepts". That's all. Of course people can and will continue to use the word "Concept" in the way they have been. But that doesn't prohibit me from using the phrase "type constraint" from referring to the original idea.
Calling it "type requirements" would be fully backed by the SGI document. [...]
But with C++11 it's much more interesting. I just came upon:
http://en.cppreference.com/w/cpp/concept First sentence: "A concept is a term that describes a *named set of requirements* for a type"
which echoes my views on the whole subject. I don't have the C++11 spec - but I'm assuming/hoping that these type requirements are part of it. This section only defines the named type requirements.
Cheers, Roland
On 2014-08-05 17:29, Robert Ramey wrote:
I believe that "C++ Concept" was originally defined by the following web page or writing contemporary to it. https://www.sgi.com/tech/stl/stl_introduction.html . A relevent quote is
"One very important question to ask about any template function, not just about STL algorithms, is what the set of types is that may correctly be substituted for the formal template parameters. Clearly, for example, int* or double* may be substituted for find's formal template parameter InputIterator. "
It's somewhat off topic, but I'm going to take the opportunity to point out https://www.sgi.com/tech/stl/doc_introduction.html . I've come to believe that C++ libraries - in particular parameterized types, are best described by the documentation approach embodied in this link. It is sufficiently formal where it has to be - but not so formal that one gets too bogged down. I've made a big point of this inhttp://rrsd.com/blincubator.com/requirements_documentation/ . My criticism of the HANA documentation is really that it fails to follow this format and content. I haven't read enough documentation on Hana to comment on that, but I agree in principle that uniformity, consistency, use of concepts etc are extremely useful to enhance documentation. I have my doubts though, that
One of the objections raised to my criticism is that this form of documentation is in some sense not modern, specific to STL, or in some way not a good model for all C++ libraries. It is this idea which I reject - totally. Library authors would be best served by producing this form of documentation (concurrently with code) and not spend any time re-inventing their own documentation form. Use this one and spend your time on coding! As of now, I'd say that the STL documentation provides a good starting
"we call such a set of type requirements a /concept/. [...] We say that a type /conforms to a concept/, or that it /is a model of a concept/, if it satisfies all of those requirements". the STL documentation structure can be used as-is in a reasonable way for every library. For instance I would not know how to do that for sqlpp11, but I would love to discuss it over a beer at CppCon. point for the documentation structure of most libraries (maybe all, I don't know). But adaptations might be required to make it fit to specific libraries.
Another interesting quote is:
"Concepts are not a part of the C++ language; there is no way to declare a concept in a program, or to declare that a particular type is a model of a concept. "
[...]
But with C++11 it's much more interesting. I just came upon:
http://en.cppreference.com/w/cpp/concept
which echoes my views on the whole subject. I don't have the C++11 spec - but I'm assuming/hoping that these type requirements are part of it. This section only defines the named type requirements.
But wait!!!! there's more !!!
For A good number of the concepts - example DefaultConstructable http://en.cppreference.com/w/cpp/concept/DefaultConstructible -there exists a constexpr function such as http://en.cppreference.com/w/cpp/types/is_default_constructible .
Small correction: These are not constexpr functions, they are template structs with a value.
So in this case we DO have concepts built into the language (libraries). Making a concept checking class would be as simple is:
template<class T> struct DefaultConstructible { static_assert(std::is_default_constructible<T>::value, "Class is not default constructible"); }; Personally, I would say that is_default_constructible already is the concept checking template. What you do with it is another question. You can use in combination with static_assert if you want to emit a hard error or you could use it with enable if, if you want to suppress non-matching instances.
Making a new concept class is pretty simple - leave as an excursive for the reader
But wait - there's even more!!!!
if there were a type trait defined for each concept - we would have type dispatching based on named type requirements - example
std::enable_ifstd::is_default_constructible<T> void f(const T &t);
It makes for a coherent and complete system from coding to documentation. Since most of this is "form filling" it's easy, mechanical and almost guaranteed to be correct. It certainly is a good foundation. It might get a bit more complex if you have variadic templates and/or constraints for the current set of
This works, if f is a template itself, but not if it is a function
inside a template like this:
template<typename T>
struct X
{
typename std::enable_if
This is the direction we (Boost and all of C++) need to go. That is, we've known what to do for some time we just have to start doing more.
Cheers, Roland
Small correction: These are not constexpr functions, they are template structs with a value.
Why does that matter? An integral constant type trait is the common way to define a concept predicate in C++, and it has many advantages over constexpr functions(which are quite limited).
This works, if f is a template itself, but not if it is a function inside a template like this:
template<typename T> struct X { typename std::enable_ifstd::is_default_constructible<T::value, void>::type f(); };
Well, actually you can if you use a default template parameter:
template<typename T>
struct X
{
template
Now, the cool thing about the (hopefully) soon to be arriving Concept Lite is, that even that will work
Most of functionality of Concepts Lite can already can be done in C++, currently. It adds some syntatic sugar(which is not bad), and it trades in specialization for clever overloading.
It makes for a coherent and complete system from coding to documentation. Since most of this is "form filling" it's easy, mechanical and almost guaranteed to be correct. It certainly is a good foundation. It might get a bit more complex if you have variadic templates and/or constraints for the current set of parameters. For instance, "no type must occur more than once in the parameter list"
Well, checking "no type must occur more than once in the parameter list" should be very possible to check. Actually, one of the big limitations of the current way to check type requirements(that includes both Boost.ConceptCheck and Concepts Lite) is that you can't check for template members or for template functions. It is possible to check for a function or member function that is callable with a certain parameters, but it is not possible to check in general(like how you can check for a template class). However, language limitations of checking for certain type requirements should not limit the documentation of those requirements. Although, it may be wise to avoid building requirements around those limitations. Regards, Paul Fultz II -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 2014-08-06 00:38, pfultz2 wrote:
Small correction: These are not constexpr functions, they are template structs with a value. Why does that matter? Just the interface. Otherwise, no. An integral constant type trait is the common way to define a concept predicate in C++, and it has many advantages over constexpr functions(which are quite limited).
This works, if f is a template itself, but not if it is a function inside a template like this:
template<typename T> struct X { typename std::enable_ifstd::is_default_constructible<T::value, void>::type f(); }; Well, actually you can if you use a default template parameter: Of course, f is then a template itself, as I said :-)
But thanks for the hint. I was not aware of this default bool trick and am thinking about using it right now...
template<typename T> struct X { template
= 0> void f(); }; Although I do find the boilerplate for `enable_if` ugly(even with the type alias) and error-prone
Me too, but I leave them unhidden and will feel great happiness when cleaning up the mess with Concepts Lite (or so I hope).
, so thats why I always use these set of macros like these:
#define CLASS_REQUIRES(...) typename std::enable_if<(__VA_ARGS__)>::type #define REQUIRES(...) typename std::enable_if<(__VA_ARGS__), int>::type = 0 #define MEMBER_REQUIRES(...) template
So you could write it like this:
template<typename T> struct X { MEMBER_REQUIRES(std::is_default_constructible<T>()) void f(); }; That looks quite nice indeed.
Now, the cool thing about the (hopefully) soon to be arriving Concept Lite is, that even that will work Most of functionality of Concepts Lite can already can be done in C++, currently. It adds some syntatic sugar(which is not bad), and it trades in specialization for clever overloading. Strong spices, I'd say, very tasty and much healthier than all that sugar ;-)
Personally, I expect a similar impact as with auto.
It makes for a coherent and complete system from coding to documentation. Since most of this is "form filling" it's easy, mechanical and almost guaranteed to be correct. It certainly is a good foundation. It might get a bit more complex if you have variadic templates and/or constraints for the current set of parameters. For instance, "no type must occur more than once in the parameter list" Well, checking "no type must occur more than once in the parameter list" should be very possible to check.
Sure, that's possible and I do it with a simple type set. My point was that it might not be as mechanical as one would guess at first glance. Most type requirements deal with individual types, some deal with multiple types.
Actually, one of the big limitations of the current way to check type requirements(that includes both Boost.ConceptCheck and Concepts Lite) is that you can't check for template members or for template functions. It is possible to check for a function or member function that is callable with a certain parameters, but it is not possible to check in general(like how you can check for a template class).
However, language limitations of checking for certain type requirements should not limit the documentation of those requirements. Although, it may be wise to avoid building requirements around those limitations. +1
Best, Roland
Roland Bock-2 wrote
I have my doubts though, that the STL documentation structure can be used as-is in a reasonable way for every library.
For instance I would not know how to do that for sqlpp11, but I would love to discuss it over a beer at CppCon.
As of now, I'd say that the STL documentation provides a good starting point for the documentation structure of most libraries (maybe all, I don't know). But adaptations might be required to make it fit to specific libraries.
I make my case in http://rrsd.com/blincubator.com/requirements_documentation/ Tutorial documentation of course is another issue so exclude that for now. Basically reference documentation contains a list of: named type constraints (concepts) types and parameterized types functions The "outline" link shows what I think anyone who makes a C++ library should fill in to get good documentation (and properly factored code also!). I can't prove it, but I believe this template is effective for every C++ library. I'm looking forward to a free beer. In the meantime, you might consider taking a look a the section above as well as the Simple Tools section regarding documentation. The reference docs would be built by taking every class and template and filling out the corresponding forms for types. Part of the template docs are parameter requirements. At some point you'll find that your repeating yourself and decide to factor out common requirements and naming them - these will be your you named type requirements. After a while, you'll likely see that you have "too" many "named type requirements" and you might go back and tweak your code to diminish the multiplicity of named type requirements. When you get back with this, your library will be smaller, simpler and easier to understand and use. Take a crack at this before we talk - Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 08/05/2014 6:44 PM, Robert Ramey wrote:
As of now, I'd say that the STL documentation provides a good starting point for the documentation structure of most libraries (maybe all, I don't know). But adaptations might be required to make it fit to specific libraries.
I make my case in http://rrsd.com/blincubator.com/requirements_documentation/
Tutorial documentation of course is another issue so exclude that for now.
For what it's worth -- from the viewpoint of a newcomer to Boost (and someone who is not a developer by profession) -- I've really found the lack of consistency of documentation to be a major challenge in terms of learning what libraries are most applicable to my own needs, and how to use them. I think that there are 2 separate issues involved here: The first is layout/structure of the documentation itself, as Robert suggests in this and previous comments. The second -- and from my personal experience, the more difficult -- is the lack of a consistently-written and sufficiently descriptive explanation of the 'what, where, why, and how' of the library: What does the library do? Where should I use it? Where should I not use it? Why (explain the overall design -- why is the library structure like X)? How do I use it? I completely understand the extreme difficulty involved in trying to enforce a specific style and format of the documentation on the library authors. It has already been suggested -- whether one agrees with it or not -- that not all libraries can even fit into the same structure due to the paradigm mismatch. Perhaps this suggests that an approach to documentation standardization should take this into account -- in terms of care of not over-specifying the requirements.
Basically reference documentation contains a list of:
named type constraints (concepts) types and parameterized types functions
From my own perspective, the documentation I've read which has followed this general approach has been much easier for me to follow. On the topic of Concepts-- The issue of Concepts is clearly quite contentious; however, what does seem clear to me from following this thread is that many people believe that Boost.Concept is lacking. What is not clear to me is whether there is significant disagreement about how Boost.Concept (or its successor) should look/behave. In other words- is there any consensus on what is expected from Boost.TypeRequirements (or whatever name might better be suited to Boost.Concept's successor). Robert has been strongly advocating the use of Boost.Concept, and I completely hear his rationale. As I understand, Robert's advocacy for Boost.Concept is that despite its shortcomings, it's currently available and works within its limitations. Are there fundamental objections to this approach -- such that if a new Concepts/ TypeRequirements library was available tomorrow which alleviated the problems in Boost.Concept -- there wouldn't be any objections to expecting its use? I've been following this thread for a while, and thought I'd offer my own thoughts on the matter. Regards, Michael
Michael Levine wrote
The second -- and from my personal experience, the more difficult -- is the lack of a consistently-written and sufficiently descriptive explanation of the 'what, where, why, and how' of the library: What does the library do? Where should I use it? Where should I not use it? Why (explain the overall design -- why is the library structure like X)? How do I use it?
indeed. This is a key part of the documentation. It's also one of the more difficult to make general statements about. For this reason, although I've tried to make recommendations about this aspect, I'm not making a big deal about this. I've been focusing on the reference part of the documentation because it's an easier sell. Once we can sell this, the rest will be easier. Basically my suggestion would be: a) intro - purpose of the library with motivating examples. b) more examples and advice on library usage c) rationale - why things were done the way they were and not some other way d) reference e) acknowledgements. But as I said - this is not (yet) part of the current crusade.
I completely understand the extreme difficulty involved in trying to enforce a specific style and format of the documentation on the library authors.
I've been trying to make my case in regards to content and it's organization. I've consciously tried to avoid specifying style, format, tools etc. We have excellent examples of documentation made with the simplest of tools - see iterators - and very hard to use documentation made with the latest/great tools - see boost units. www.blincubator.com explicitly makes the case in documentation requirements and format, tools, etc is discussed in a totally different section - simple tools.
It has already been suggested -- whether one agrees with it or not -- that not all libraries can even fit into the same structure due to the paradigm mismatch. Perhaps this suggests that an approach to documentation standardization should take this into account -- in terms of care of not over-specifying the requirements.
I've taken great pains to address this - see above.
Basically reference documentation contains a list of:
named type constraints (concepts) types and parameterized types functions
From my own perspective, the documentation I've read which has followed this general approach has been much easier for me to follow.
Hallelujah!!!
On the topic of Concepts--
The issue of Concepts is clearly quite contentious; however, what does seem clear to me from following this thread is that many people believe that Boost.Concept is lacking. What is not clear to me is whether there is significant disagreement about how Boost.Concept (or its successor) should look/behave. In other words- is there any consensus on what is expected from Boost.TypeRequirements (or whatever name might better be suited to Boost.Concept's successor).
It seems that "concepts lite" is shaping up to be the next episode in an on going ten year saga. For me it makes no difference. If it ever makes it and people want to use it - fine. I even provide a table for translating boost concept classes into concepts lite code. But this is not really relevant to my argument. Basically the whole concepts discussion/development has been blown way out of proportion: a) the important thing is that library which use parameterized types need a method of specify and enforcing requirements on those types. boost concept works for this concepts lite will work for this and in fact just inserting some static asserts can work just as well for this. (I'll be updating www.blincubator.com to demonstrate this). b) very few C++ programmer right now code with parameterized types. c) even fewer publish such code. d) even fewer explicitly specify parameter type requirements. e) and even fewer actually include code to detect violations. So it's beyond me that is an issue which requires some sort of enhancement to C++ (concepts lite). I'm sure that 1/10 the amount of time disputing concepts would have been more than sufficient to specify and enforce type requirements in all the boost libraries. Just to make myself clear - the path to better library code is for library authors to specify and verify concepts - and we already have all we need to do that. If the committee want's to spend more time on this - fine - but it won't make any difference unless library writers change their habits.
Robert has been strongly advocating the use of Boost.Concept, and I completely hear his rationale. As I understand, Robert's advocacy for Boost.Concept is that despite its shortcomings, it's currently available and works within its limitations. Are there fundamental objections to this approach -- such that if a new Concepts/ TypeRequirements library was available tomorrow which alleviated the problems in Boost.Concept -- there wouldn't be any objections to expecting its use?
I wouldn't have any objections. I'm curious that no one has called for compiler changes to require type requirements on template parameters - as they are not for non-template parameters. It's odd to me that this hasn't come up (to my knowledge). Not that I'm convinced this would be a good idea. But think about it. I doubt anyone objects to the requirement that functions specify the types of their (non-template) arguments. And it wasn't always so - when I started with C - function arguments types could be omitted - in which case they defaulted to int. This caused a lot of pain - not all that unlike the pain that undefined template type requirements cause to day.
I've been following this thread for a while, and thought I'd offer my own thoughts on the matter.
Happy to hear from you - I can always use another opportunity to flog my case. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 08/12/2014 1:57 PM, Robert Ramey wrote:
Michael Levine wrote
The second -- and from my personal experience, the more difficult -- is the lack of a consistently-written and sufficiently descriptive explanation of the 'what, where, why, and how' of the library: What does the library do? Where should I use it? Where should I not use it? Why (explain the overall design -- why is the library structure like X)? How do I use it?
indeed. This is a key part of the documentation. It's also one of the more difficult to make general statements about. For this reason, although I've tried to make recommendations about this aspect, I'm not making a big deal about this. I've been focusing on the reference part of the documentation because it's an easier sell. Once we can sell this, the rest will be easier. Basically my suggestion would be:
a) intro - purpose of the library with motivating examples. b) more examples and advice on library usage c) rationale - why things were done the way they were and not some other way d) reference e) acknowledgements.
But as I said - this is not (yet) part of the current crusade.
I suppose that the question of priority depends on one's viewpoint. Nevertheless, I completely agree with you that the reference section should be the primary focus at this point. As I'm writing this, a thought came to mind and I'll just throw it out there: the library index (at the documentation page - www.boost.org/doc/libs/1_56_0) has a short one-liner about the library. I wonder if it might be possible to expand this brief summary - even just a bit - to provide a bit more information, about the main use case. This doesn't even need to be done by the library author; just someone knowledgeable about the library. I would volunteer in a flash, but I am absolutely clueless with neither knowledge or experience.
I completely understand the extreme difficulty involved in trying to enforce a specific style and format of the documentation on the library authors.
I've been trying to make my case in regards to content and it's organization. I've consciously tried to avoid specifying style, format, tools etc. We have excellent examples of documentation made with the simplest of tools - see iterators - and very hard to use documentation made with the latest/great tools - see boost units. www.blincubator.com explicitly makes the case in documentation requirements and format, tools, etc is discussed in a totally different section - simple tools.
Your incubator site is a phenomenal idea and the information/directions that you have included there are both extremely clear and sensible. Kudos.
It has already been suggested -- whether one agrees with it or not -- that not all libraries can even fit into the same structure due to the paradigm mismatch. Perhaps this suggests that an approach to documentation standardization should take this into account -- in terms of care of not over-specifying the requirements.
I've taken great pains to address this - see above.
There are quite a few dissenting opinions in this thread's history as to whether the same paradigms necessarily apply to Hana. You have made your point clearly on the matter, but there have been quite a few dissenting opinions, as well. I have my opinions on this discussion, as well, but it's a little off-topic from the rest of this particular message. Perhaps I'll address that in a separate response, if time permits.
From my own perspective, the documentation I've read which has followed this general approach has been much easier for me to follow.
Hallelujah!!!
I intended my previous message as an expression of support of your efforts, from the perspective of a beginner/novice user. Sometimes, it's hard to see that viewpoint with the level of expertise that the vast majority of library developers have.
On the topic of Concepts--
<snip>
It seems that "concepts lite" is shaping up to be the next episode in an on going ten year saga. For me it makes no difference. If it ever makes it and people want to use it - fine. I even provide a table for translating boost concept classes into concepts lite code. But this is not really relevant to my argument.
That was very helpful and enlightening.
Basically the whole concepts discussion/development has been blown way out of proportion:
I couldn't agree more.
Just to make myself clear - the path to better library code is for library authors to specify and verify concepts - and we already have all we need to do that. If the committee want's to spend more time on this - fine - but it won't make any difference unless library writers change their habits.
Is there that much disagreement -- at least within the Boost community -- on this point ? I know that Niall expressed his viewpoint that compiler support is essential before developers should embrace Concepts. I'm not completely sure that I understand his rationale on the matter, and your own arguments have long ago convinced me. Niall: Forgive me if I am misconstruing your previous comments on the matter. I understood your point to be that without compiler support (in the form of Concepts Lite, for now), there are too many limitations with a Library-based system to pursue using it in code. There was also some points regarding whether type restrictions should cause soft errors - being usable for SFINAE and specialization - and/or hard errors. IMHO, this is a moot point: clearly there are use cases for each, and a requirement for Boost.Concept (or its successor - what I've referred to above as Boost.TypeRequirements). Ultimately, in my own extremely limited understanding, it seems that the general issue here can be summarized to some extent that there are a wide range of expectations for a Concepts system. I believe that you have been advocating what I'd characterize as the most fundamental set of requirements. There is a lot more functionality and benefits that a fully-complete Concepts system can offer. I can only surmise that there is a general reluctance to adopt a system that people feel doesn't achieve all of the aims that they expect from it, coupled with a concern for needing to revise code once language /compiler support evolves. I'd really like to hear comments from everyone on this, and would invite everyone -- especially people who disagree with Robert -- to share your thoughts on this: - Is my conjecture correct? Or do those of you who object to Robert's position have other reasons? - Is there anything -- short of full language support -- that you require in order to embrace template parameter Type Requirements? - What are the show-stoppers in Boost.Concept that have led you to reject its use.
I've been following this thread for a while, and thought I'd offer my own thoughts on the matter.
Happy to hear from you - I can always use another opportunity to flog my case.
Robert Ramey
Unfortunately, your preaching to the choir in my case. But I do find your response to provide deeper insight into the points that you have already written on the bl incubator site. Best regards- Michael Levine
On 13 Aug 2014 at 13:42, Michael Levine wrote:
Is there that much disagreement -- at least within the Boost community -- on this point ? I know that Niall expressed his viewpoint that compiler support is essential before developers should embrace Concepts. I'm not completely sure that I understand his rationale on the matter, and your own arguments have long ago convinced me. Niall: Forgive me if I am misconstruing your previous comments on the matter. I understood your point to be that without compiler support (in the form of Concepts Lite, for now), there are too many limitations with a Library-based system to pursue using it in code.
You're a little misconstrued :) Totally understandable given the length of the thread. The main essence of my objection is that Concepts Lite will make the C++ 17 compiler a much more powerful assembler macro compiler than the C++ 14 compiler. Concepts Lite are far "closer to the metal" in letting you directly instruct the compiler on what macro fragments to compose you see, so you can skip leaping through SFINAE and all the other legacy syntax workarounds and tricks. That should very substantially reduce memory consumption and compilation time for compiler programming. It may even be useful to have positive effects on metaprogramming brittleness - Andrew himself will tell you he has no idea on the outcome here, it could go either way. So tl;dr; I am really saying the time for concepts - whatever they are to whoever's definition - isn't here yet. Let's get a few concept programming libraries based on a Concepts Lite compiler around first. Let's not dig ourselves now into a straightjacket we later regret. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
Niall Douglas wrote
So tl;dr; I am really saying the time for concepts - whatever they are to whoever's definition - isn't here yet.
I would disagree. The whole STL library is based on "concepts". That is, all template parameter have explicit requirements. This is true now and has always been so. It's true that compiler support for verification of all the type requirements which someone might come up with falls short of perfection. But as a practical matter, most type requirements are pretty simple and easily supported with current type traits. For example, type requirements for template<class T> quick_sort(iterator<T> begin, iterator<T> end) are easily stated AND enforced: BOOST_CONCEPT_REQUIRES((Swappable<T>); BOOST_CONCEPT_REQUIRES((StrictWeakOrdering<T>)); This is useful right now. And few library authors even explicitly state their type requirements - much less include them in code. This could change in a month - and it will if I have anything to say about it. There is absolutely no advantage to not doing this.
Let's get a few concept programming libraries based on a Concepts Lite compiler around first. Let's not dig ourselves now into a straightjacket we later regret.
I've included a table which maps boost concept library macros to the concept lite syntax. see http://rrsd.com/blincubator.com/advice_concepts/ "Future Compatibility". Concepts lite is not really relevant here. It won't change the landscape in any way. Library authors aren't failing to explicitly define and enforce their type requirements because they lack compiler support for this. They're doing it because we don't demand that we do so. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On Wed, 13 Aug 2014, Robert Ramey wrote:
It's true that compiler support for verification of all the type requirements which someone might come up with falls short of perfection. But as a practical matter, most type requirements are pretty simple and easily supported with current type traits. For example, type requirements for
template<class T> quick_sort(iterator<T> begin, iterator<T> end)
are easily stated AND enforced: BOOST_CONCEPT_REQUIRES((Swappable<T>); BOOST_CONCEPT_REQUIRES((StrictWeakOrdering<T>));
This is useful right now. And few library authors even explicitly state their type requirements - much less include them in code.
This could change in a month - and it will if I have anything to say about it. There is absolutely no advantage to not doing this.
In general, yes, there is an advantage to not doing this: checking the requirements this way triggers some instantiations that you may need to delay. That's the main reason libstdc++ deprecated their concept checks (based on an early version of boost's), they broke too much code that ended up with cycles of A needs B needs C needs A. -- Marc Glisse
2014-08-14 8:00 GMT+02:00 Robert Ramey
Niall Douglas wrote
So tl;dr; I am really saying the time for concepts - whatever they are to whoever's definition - isn't here yet.
I would disagree. The whole STL library is based on "concepts". That is, all template parameter have explicit requirements. This is true now and has always been so.
It's true that compiler support for verification of all the type requirements which someone might come up with falls short of perfection. But as a practical matter, most type requirements are pretty simple and easily supported with current type traits. For example, type requirements for
template<class T> quick_sort(iterator<T> begin, iterator<T> end)
are easily stated AND enforced: BOOST_CONCEPT_REQUIRES((Swappable<T>); BOOST_CONCEPT_REQUIRES((StrictWeakOrdering<T>));
This is useful right now. And few library authors even explicitly state their type requirements - much less include them in code.
This could change in a month - and it will if I have anything to say about it. There is absolutely no advantage to not doing this.
There appears to be a number of things where Robert and Niall would agree: 1. A library with templates in the interface should _document_ the requirements: in html or similar documentation 2. Unless there are reasons to do otherwise, such library should attempt to issue a diagnostic message during compilation that the requirements on types have not been satisfied. This doesn't need to be Boost.ConceptCheck (if no consensus can be reached on using it). Probably a static assert with a type trait should be enough: template<class T> quick_sort(iterator<T> begin, iterator<T> end) { static_assert(is_less_than_comparable<T>::value, "T is not LessThanComparable"); static_assert(is_swappable<T>::value, "T is not Swappable"); // do the work } Not an ideal, but perhaps less controversial. Regards, &rzej
On 14 Aug 2014 at 9:37, Andrzej Krzemienski wrote:
This could change in a month - and it will if I have anything to say about it. There is absolutely no advantage to not doing this.
There appears to be a number of things where Robert and Niall would agree:
I think myself and Robert are maybe even 90% in fundamental agreement. It's funny actually, because we both started off quite far away from one another in opinion and he has changed his opinion to become closer to mine in many areas, and I thank him for that. I can't say how much I've changed my opinion to more closely match his as it's hard to see yourself from the outside, but I will say this: despite that I don't think his Incubator stands a chance because the Boost culture is the true problem so he's trying to substitute technological fixes for cultural problems, I am absolutely happy to support his effort there and I truly hope I am wrong and he is right on that (I might add that AFIO was one of the very first libraries - the second? - to be added to the Incubator). No, where I am fundamentally coming from is asking the question "why do engineers like Dave Abrahams leave Boost?" Of course only Dave knows that, and it's his business anyway so you should ignore the named personalisation, but I find it an extremely useful abstract thought exercise about the wider cultural malaise and what's gone wrong. And, for the record, Dave leaving did harden my attitudes significantly. I suspect the same is true for Robert.
1. A library with templates in the interface should _document_ the requirements: in html or similar documentation
We're definitely in strong agreement that documentation needs to be better. There is some significant variance in what better means.
2. Unless there are reasons to do otherwise, such library should attempt to issue a diagnostic message during compilation that the requirements on types have not been satisfied. This doesn't need to be Boost.ConceptCheck (if no consensus can be reached on using it). Probably a static assert with a type trait should be enough:
template<class T> quick_sort(iterator<T> begin, iterator<T> end) { static_assert(is_less_than_comparable<T>::value, "T is not LessThanComparable"); static_assert(is_swappable<T>::value, "T is not Swappable"); // do the work }
Not an ideal, but perhaps less controversial.
The above is what I do in my own code - indeed, just last night I
wrote this for my concurrent_unordered_map:
/*! \brief Factory function for many node_ptr_types, optionally
using an array of preexisting
memory allocations which must be deallocatable by this container's
allocator.
*/
template<class InputIterator> std::vector
-----Original Message----- From: Boost [mailto:boost-bounces@lists.boost.org] On Behalf Of Niall Douglas Sent: 14 August 2014 12:36 To: boost@lists.boost.org Subject: Re: [boost] [Concepts] Definition. Was [GSoC] [Boost.Hana] Formal review request
2. Unless there are reasons to do otherwise, such library should attempt to issue a diagnostic message during compilation that the requirements on types have not been satisfied. This doesn't need to be Boost.ConceptCheck (if no consensus can be reached on using it). Probably a static assert with a type trait should be enough:
template<class T> quick_sort(iterator<T> begin, iterator<T> end) { static_assert(is_less_than_comparable<T>::value, "T is not LessThanComparable"); static_assert(is_swappable<T>::value, "T is not Swappable"); // do the work }
Not an ideal, but perhaps less controversial.
The above is what I do in my own code - indeed, just last night I wrote this for my concurrent_unordered_map:
/*! \brief Factory function for many node_ptr_types, optionally using an array of preexisting memory allocations which must be deallocatable by this container's allocator. */ template<class InputIterator> std::vector
node_ptrs(InputIterator start, InputIterator finish, value_type **to_use=nullptr) { static_assert(std::is_same ::value>::type, "InputIterator type is not my value_type");
At the same time as doing this, you could easily also add something like \tparam InputIterator InputIterator A type that must match value_type. This can include user-helpful examples and other info (does it have to be a built-in type say). and this would show up in any automatically generated reference documentation system, for example Doxygen (along with your description " Factory function for many node_ptr_types"). <big snip> Paul --- Paul A. Bristow Prizet Farmhouse Kendal UK LA8 8AB +44 (0) 1539 561830
On 14 Aug 2014 at 13:06, Paul A. Bristow wrote:
At the same time as doing this, you could easily also add something like
\tparam InputIterator InputIterator A type that must match value_type. This can include user-helpful examples and other info (does it have to be a built-in type say).
and this would show up in any automatically generated reference documentation system, for example Doxygen (along with your description " Factory function for many node_ptr_types").
Oh for sure, if I were writing docs for that code yet. Right now the docs are merely notes to remind me of stuff. Once the implementation is well tested, I'll post it here for a mini-review. I'll then move onto non-allocating future-promise. I'm doing concurrent_unordered_map first because it will help hugely with testing non-allocating future-promise. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
Hi, the commit for the modification of BOOST_ARCHIVE_VERSION from 10 to 11 in modular-boost repo is not documented, except that it is due to release. What is the reason for 1.55 and 1.56 archive not being compatible (nothing in release notes). Greetz, Ingo.
LOL - probably should pick a different thread. Ingo.Loehken wrote
Hi,
the commit for the modification of BOOST_ARCHIVE_VERSION from 10 to 11 in modular-boost repo is not documented, except that it is due to release.
What is the reason for 1.55 and 1.56 archive not being compatible (nothing in release notes).
Hmmm - I would be very surprised to find that this change - made with every boost release - makes archives incompatible. That wouldn't be my intention. Perhaps you should open a trac item for this. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
Niall Douglas wrote
Anyway, if I feel that bad template parameters would generate unhelpful error messages, I'll usually throw in some sort of clarifying static_assert like the above. I view these as very similar to C-style asserts - there to be useful during development, not as parameter constraints.
This is exactly how I got to where I am now. When I wrote the serialization library, I could see users plugging in invalid type parameters and getting back a raft of useless error messages. So, one by one, I inserted static asserts to trap all this. I couldn't emit my own error message, so this code is riddled with "If your compiler emits an error here, ..." I even created BOOST_STATIC_WARNING to trap situations which though legal - were highly suspect. legal suspects if you will. Then I needed to get the documentation done. I just couldn't get it right. I couldn't figure out how to describe the T in template<class T> f(...) where T wasn't a particular type. My attempts to document the serialization library without this knowledge led to a long discussion on this subject. During the whole time I never figured this out. Since I'm a smart, stubborn guy that didn't really understand the idea - and David Abrahams was involved, you can imagine that it was a pretty circular, pointless and contentious discussion. Eventually the penny dropped and I got the documentation fixed up. I never did go back and change the static asserts. They're not wrong - but having them directly relatable to the explicit concepts in the documentation would have made them less ad hoc. Also, it would have made explicit a bunch of underlying assumptions in the code. It would have made me see that I had several similar ideas which could have been consolidated. In short it would have given me a framework for making simple, more understandable and less incorrect code and avoided some asymmetries which haunt the code to this day. Maintaining backward archive capability would mean a lot more work to make these changes today. I had looked at Boost Concept library and the stl documentation and it made no sense to me. Sometime after the discussion referred to above I figured all this out. I always felt that I was mislead by the pesky word "concept". So my argument that it be dropped in favor of "type requirements" or "type constraints" is not theoretical - it's motivated by pure pragmatism. So I've come to believe that it absolutely necessary that type requirements be explicitly defined. (Otherwise how could we define their enforcement.) So these requirements have to in the documentation. (Otherwise how is a user to know what they are? ). Again, I haven't specified and detailed form or any specific documentation tools, I'm limited my argument to saying that the type requirements on every template parameter must be documented and enforced if possible
It is odd how profound philosophical disagreement can have such little real effect on code written -
Really, I don't see it as a philosophical or theoretical issue but rather a purely pragmatic one. My views and arguments are motivated by real experience which I hope to spare future library authors. (and users).
someone should really write a book on that topic actually.
lol - I hope not. OK - I'll write the world's shorted C++ programming book. Template Type Requiements by Robert Ramey All template type requirements need to be defined - otherwise how can they be implemented? Hence, these definitions need to be documented - otherwise how can users know what they are? Hence, they need to be enforced, because users won't read the documentation until they get an error. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 14 Aug 2014 at 8:45, Robert Ramey wrote:
Anyway, if I feel that bad template parameters would generate unhelpful error messages, I'll usually throw in some sort of clarifying static_assert like the above. I view these as very similar to C-style asserts - there to be useful during development, not as parameter constraints. [snip] Eventually the penny dropped and I got the documentation fixed up. I never did go back and change the static asserts. They're not wrong - but having them directly relatable to
Niall Douglas wrote the explicit concepts in the documentation would have made them less ad hoc. Also, it would have made explicit a bunch of underlying assumptions in the code. It would have made me see that I had several similar ideas which could have been consolidated. In short it would have given me a framework for making simple, more understandable and less incorrect code and avoided some asymmetries which haunt the code to this day. Maintaining backward archive capability would mean a lot more work to make these changes today.
I think this is the crux of our difference. You believe that type constraints are a good thing, and that structures of constrained type relations build meaning and enables better communication in documentation. I on the other hand believe that type constraints pre-Concepts-Lite are a bad thing, and I wish the compiler wasn't so stupid - moreover, I know the compiler soon won't be so stupid. I see them as input sanitisers as a necessary evil, and they at best might be occasionally useful but generally they just get in the way and make code brittle both now and in the future. Hence they get used as sparingly as possible in assertion checks. I obviously use them extensively in metaprogramming, but that's constraining /selection/ of implementation which is opposite to sanitising inputs.
So I've come to believe that it absolutely necessary that type requirements be explicitly defined. (Otherwise how could we define their enforcement.) So these requirements have to in the documentation. (Otherwise how is a user to know what they are? ). Again, I haven't specified and detailed form or any specific documentation tools, I'm limited my argument to saying that the type requirements on every template parameter must be documented and enforced if possible
I have no problem with implicitly defined, and are an informal consensus. I do have an especial problem with their effect on documentation. That said, I have never used your Serialisation library. Maybe if I do one day I may realise that concepts or type constraints have nothing to do with good or bad documentation, and my negative association is merely an artefact of random chance.
It is odd how profound philosophical disagreement can have such little real effect on code written -
Really, I don't see it as a philosophical or theoretical issue but rather a purely pragmatic one. My views and arguments are motivated by real experience which I hope to spare future library authors. (and users).
I would say exactly the same about my own. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
Niall Douglas wrote
That said, I have never used your Serialisation library. Maybe if I do one day I may realise that concepts or type constraints have nothing to do with good or bad documentation, and my negative association is merely an artefact of random chance.
I think a better examples of the way boost libraries should be built upon explicit type constraints can be found in other libraries such as fusion, iterators, range, graph and others. These were built with understanding of type constraints at the start, rather than discovered after the fact as in my case. References to the serialization library in this context are really just to motivate readers to avoid my pain by benefiting from my first hand experience and to demonstrate that with enough persistence, even a re-invented wheel can made to roll. You might try putting these propositions to the test by seeing what happens when one tries to explicitly specify type requirements to AFIO - assuming this has yet to be done. It would be interesting to know if this weren't possible. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 15 Aug 2014 at 12:42, Robert Ramey wrote:
You might try putting these propositions to the test by seeing what happens when one tries to explicitly specify type requirements to AFIO - assuming this has yet to be done. It would be interesting to know if this weren't possible.
Ah, this isn't needed in AFIO. And I suppose it is useful to explain
why.
AFIO is pure batch, so all APIs consume and emit std::vector<T> where
T is an API-specific type. The mapping looks like this (subset):
vector
<= enumerate() <= vector
In other words, inputs are very strongly typed, and the input
containers do considerable static and dynamic sanity checking. For
example, read() and write() both accept vectors of
async_data_op_req<T>, and async_data_op_req<T> will implicitly
construct itself from any of:
1. boost::asio::const_buffer and mutable_buffer, or std::array or
std::vector of const_buffer and mutable_buffer.
2. const T * and T * if also supplied with a size_t length and T is
trivial.
3. const std::array
My position - broadly stated is a) All template parameters should have explicit type requirements. b) such type requirements should be documented c) and such type requirements should be explicitly enforced in the code. Not explicitly stated, but implicit in a above is d) It is possible and useful to assign type requirements for all C++ template code. You've stated that AFIO is a counter-example to d) above. I'm confident you'll let me know if I've got your position wrong. So ... This is the first time I've actually looked into the AFIO documentation. I found it very interesting. I'm going to critique it later in detail as it deserves a larger effort than I can justify right now. Robert Ramey PS - I'll likely post this critique as a comment on the blincubator as I want to test/demo this platform for this purpose. It's very hard to get this stuff right the first time so bear with me. RR -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 16 Aug 2014 at 10:05, Robert Ramey wrote:
You've stated that AFIO is a counter-example to d) above. I'm confident you'll let me know if I've got your position wrong.
I think the disagreement for the code enforcement part, not the documentation part, is probably about mechanism and intent not outcome.
This is the first time I've actually looked into the AFIO documentation. I found it very interesting. I'm going to critique it later in detail as it deserves a larger effort than I can justify right now.
I'm always very interested in constructive feedback. Do remember the API is designed to be used indirectly as part of an eventual monadic continuations framework, though direct use will always be the most efficient of course. As the tutorial demonstrates, usage fragments into bitty unmaintainable callbacks at scale if you are using the API directly. The design rationale at the front is out of date after my C++ Now 2014 presentation and I need to update it. It's not terrible though.
PS - I'll likely post this critique as a comment on the blincubator as I want to test/demo this platform for this purpose. It's very hard to get this stuff right the first time so bear with me.
I just updated AFIO's entry there to match current. Does it email me when a comment is posted? If not, do ping me when it's ready. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
Niall Douglas wrote
On 16 Aug 2014 at 10:05, Robert Ramey wrote: I'm always very interested in constructive feedback. Do remember the API is designed to be used indirectly as part of an eventual monadic continuations framework, though direct use will always be the most efficient of course. As the tutorial demonstrates, usage fragments into bitty unmaintainable callbacks at scale if you are using the API directly.
Well, I'll look at with no pre-conceptions - as any prospective user would. So if there's something special I should keep in mind, it would best be in the documentation somewhere - otherwise I won't know about it - don't depend on my memory - I don't.
I just updated AFIO's entry there to match current. Does it email me when a comment is posted?
amazingly, I can't answer that. The whole thing depends on a bunch of plug-ins many of which have unobvious behavior. So I've found the only real way to know what is going to happen is to try it. I hate spending time on this, but it's the only way I've found short of writing the code myself - which is even worse.
If not, do ping me when it's ready.
Niall
I'll ping the list Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
With an eye to verifying the existence of library using templates which would not benefit from explicit type constraints I went through some of the documentation of AFIO. I posted a log of my notes as I went through it here: http://rrsd.com/blincubator.com/open-content/#comment-26 Of necessity, it sort of rambles around before it gets to the main point. That's because I had to start at the beginning in order to have enough context to understand it. Short version a) I don't think this library demonstrates that type constraints wouldn't help. In fact I think the opposite. b) This further reinforces my view that DOxygen is not a great system for writing C++ documentation. c) AFIO is much more complicated than I think it has to be - but I can't prove this because its so hard to understand anything about it. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 17 Aug 2014 at 18:32, Robert Ramey wrote:
With an eye to verifying the existence of library using templates which would not benefit from explicit type constraints I went through some of the documentation of AFIO. I posted a log of my notes as I went through it here:
A strange location for a comment. Why not on the AFIO review page?
Of necessity, it sort of rambles around before it gets to the main point. That's because I had to start at the beginning in order to have enough context to understand it.
You actually made some very valid points, points which were facepalm obvious. Thank you. I tried hitting reply, but there appears to be no mechanism for quoting which would make a rebuttal confusing and messy. I can rebut here (about half your observations are already answered in the docs), or am I wrong about the lack of quoting? FYI you had some unfortunate timing, last night just after I went to bed my DSL modem decided to go into a bootloop, so my CI was offline till 9am this morning when I power cycled the modem. Hence all the documentation was not online. Due to continuing DSL modem instability, I am already in the process of relocating AFIO documentation to be autopushed onto github after each CI run, in fact I only completed the refactoring of the CI innards to achieve this three weekends ago and last week was my daughter's christening.
a) I don't think this library demonstrates that type constraints wouldn't help. In fact I think the opposite. b) This further reinforces my view that DOxygen is not a great system for writing C++ documentation.
Its two big advantages are that both Eclipse and Visual Studio will show tooltips of the API doc when you hover over it, plus it has exceptionally low maintenance. Otherwise I agree, it's not bad for Qt C++, but not good for Boost C++. I am unaware of a superior alternative in maintenance costs.
c) AFIO is much more complicated than I think it has to be - but I can't prove this because its so hard to understand anything about it.
On the last point I will say this: AFIO is clean, logical and simple only when compared to other asynchronous i/o libraries. The Windows overlapped i/o API, libuv and of course the POSIX aio API come to mind, all of which have their own weird quirks too. You may find the reverse engineered docs for Linux's KAIO async i/o API at http://www.fsl.cs.sunysb.edu/~vass/linux-aio.txt illustrative as to what I mean about API complexity. There are also a list of caveats, gotchas and quirks for using Linux KAIO at https://code.google.com/p/kernel/wiki/AIOUserGuide which AFIO makes disappear for you so you don't need to think about them [1]. In other words, the lack of complexity is entirely relative to its peers only. I agree that in absolute terms 98% of people needing to do storage don't need async i/o. This is why AFIO will never be popular enough to find a review manager. [1]: AFIO doesn't support the Linux KAIO API yet, we ran out of time during GSoC 2013. But the design accomodates the Linux quirks as well as it does the Windows quirks, and a lot of non-obvious effort was expended very early on to make a design which would hide platform-specific implementation detail so well. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
Niall Douglas wrote
On 17 Aug 2014 at 18:32, Robert Ramey wrote:
With an eye to verifying the existence of library using templates which would not benefit from explicit type constraints I went through some of the documentation of AFIO. I posted a log of my notes as I went through it here:
A strange location for a comment. Why not on the AFIO review page?
I have envisioned the AFIO library page as a sort of permanent running log - similar or as a replacement for the threaded discussions on this list. The idea is that much of the rationale and discussion is useful to users and future maintainers of the library. Another use would be general reference. On the Hana discussion there was reference to a somewhat related discussion regarding a library proposal many years ago - FC++. This was a functional programming system rendered in C++. It seems it was a "bridge too far" at the time. But it would have been interesting to have had it around in the incubator along with the very interesting discussion and reviews. So far it's not working out this way - but I'm hoping that it will eventually take off. We'll just have to wait and see. I didn't see my comments as being appropriate for some permanent record for AFIO. Also I wanted to take my "Library Writers Workshop" for a dry run. My method is to just start reading the docs recording my questions and observations as I go along. This is fairly easy to do - maybe a little tedious - but I think very useful. Note that one can't do it for his own library because he knows too much. Hence the design of the "Library Writer's Workshop". Again, it's sort of "dry run" so see how that pans out.
Of necessity, it sort of rambles around before it gets to the main point. That's because I had to start at the beginning in order to have enough context to understand it.
You actually made some very valid points, points which were facepalm obvious. Thank you. I tried hitting reply, but there appears to be no mechanism for quoting which would make a rebuttal confusing and messy.
OK - I'll try to figure out how to insert quoting. I'm not sure that "rebuttal" is the right term. I'm not really trying to make an argument - but just recording my observations while reading through. If one gets something wrong while doing this that either the person doing the review isn't prepared to do it or the documentation needs some enhancement in order to make it easier to understand. Or maybe something just needs fixing. It's meant to be helpful without being directly critical.
I can rebut here (about half your observations are already answered in the docs), or am I wrong about the lack of quoting?
FYI you had some unfortunate timing, last night just after I went to bed my DSL modem decided to go into a bootloop, so my CI was offline till 9am this morning when I power cycled the modem. Hence all the documentation was not online.
Due to continuing DSL modem instability, I am already in the process of relocating AFIO documentation to be autopushed onto github after each CI run, in fact I only completed the refactoring of the CI innards to achieve this three weekends ago and last week was my daughter's christening.
No problem. There was enough for my cursory examination.
a) I don't think this library demonstrates that type constraints wouldn't help. In fact I think the opposite. b) This further reinforces my view that DOxygen is not a great system for writing C++ documentation.
Its two big advantages are that both Eclipse and Visual Studio will show tooltips of the API doc when you hover over it, plus it has exceptionally low maintenance. Otherwise I agree, it's not bad for Qt C++, but not good for Boost C++. I am unaware of a superior alternative in maintenance costs.
I've collected my views on documentation tools at http://rrsd.com/blincubator.com/tools_documentation/ I much appreciate the appeal of DOxygen as far as convenience is concerned. I included an analysis of it for our purposes in the above link. Summary: a) I like the idea of "literate programming" which DOxygen attempts to embody. b) I agree that they've made maintenance of reference documentation much simpler. c) It can work well for class libraries and functions d) it fails utterly for templates whose type parameters are not specific classes. e) it makes the code headers messy and hard to read directly. f) programmers - being basically lazy people who don't like to write much which isn't actual code - generally end up writing comments which just parrot the code - limiting it's utility. It deludes programmers into thinking they are actually documenting a library when they actually aren't g) It doesn't address critical parts of the process such as motivation, examples, etc. The link above discusses the the options for creating documentation for boost libraries. All have been used with success. The one I use is XMLMind to generate boostbook xml. Seems it's not for everyone - but I'm happy with it. To me this is the most valuable and interesting part of the this discussion. I'm less interested in AFIO in particular here than what I view as the "right (easiest and most useful)" way to create a complete boost quality C++ library. I see a lot off efforts with very clever and advanced coding in which authors have invested huge amount of effort, which fail to get traction for lack of all the rest of that which makes for a good library. The whole goal behind the incubator is to sell my ideas on how to make the process easier so motivate authors are more likely to avoid disappointment. Of course these are my personal ideas - but (lol) so far no one has posted any comments disputing them.
c) AFIO is much more complicated than I think it has to be - but I can't prove this because its so hard to understand anything about it.
On the last point I will say this: AFIO is clean, logical and simple only when compared to other asynchronous i/o libraries. The Windows overlapped i/o API, libuv and of course the POSIX aio API come to mind, all of which have their own weird quirks too.
You may well be right that it can be made no simpler - I can't defend my proposition that I think it must be possible to make it simpler.
In other words, the lack of complexity is entirely relative to its peers only. I agree that in absolute terms 98% of people needing to do storage don't need async i/o. This is why AFIO will never be popular enough to find a review manager.
I have used asyncio both the windows api and linux api version and have found them to be almost unusable and very, very, very difficult to get right. I very much aware of the utility of such a library to improve performance and to help properly factor and decouple i/o bottle necks from the rest of the application. I also believe that many users would find such a library very useful and would want to use it - if it were easy enough to use. This is the task of the library writer - to make the unusable usable. so I would say you're not thinking big enough. if AFIO is not simple enough to be used within an hour of looking over the docs, it's too complicated. Think bigger!!!! What would be an ideal interface ? is there a way to implement it? For example: main(..){ // example one asyncio::istream ais("filename"); // works almost like a stream int x; ais >> x; // read an x .... ais.sync() // example two completion_function_object cfo = [](....); asyncio::istream ais("filename", cfo); ais >> x; // read an x, invoke cfo on completion // example three - cfo is created as an io manipulator ais >> x >> cfo; // example four - cfos and cfoy are created as io manipulators ais >> x >> cfox >> y >> cfoy; } // documentation concept: StandardInputStream // list off all the functions that a standard stream has to support type asyncio::istream<S> type requirement: S ful fills the requirements of StandardInputStream legal operations ais << T type requirement: the operation is >> t must be valid - where is a StandardInputStream This is something all of can understand in a few minutes. It would be a hugely popular boost library. I personally would look forward to using it. And you know what? I bet you already have all the code written for it. Just start at the top - create some simple ref doc as above, create the short header for asycio::istream, and use that to redirect to the functions you already have. Of course this is very speculative thoughts - its before breakfast for me here - so feel free to take it with a kilo of salt. Good luck with this. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 18 Aug 2014 at 9:54, Robert Ramey wrote:
You actually made some very valid points, points which were facepalm obvious. Thank you. I tried hitting reply, but there appears to be no mechanism for quoting which would make a rebuttal confusing and messy.
OK - I'll try to figure out how to insert quoting.
I'll let you get the quoting reply thing working before I reply on that site. You made some excellent very valid points I will fix immediately, but many of them were answered in the docs already.
To me this is the most valuable and interesting part of the this discussion. I'm less interested in AFIO in particular here than what I view as the "right (easiest and most useful)" way to create a complete boost quality C++ library. I see a lot off efforts with very clever and advanced coding in which authors have invested huge amount of effort, which fail to get traction for lack of all the rest of that which makes for a good library. The whole goal behind the incubator is to sell my ideas on how to make the process easier so motivate authors are more likely to avoid disappointment. Of course these are my personal ideas - but (lol) so far no one has posted any comments disputing them.
Where we diverge the most strongly is in what we think "easier" to mean. But I won't bother rehashing all that again.
c) AFIO is much more complicated than I think it has to be - but I can't prove this because its so hard to understand anything about it.
On the last point I will say this: AFIO is clean, logical and simple only when compared to other asynchronous i/o libraries. The Windows overlapped i/o API, libuv and of course the POSIX aio API come to mind, all of which have their own weird quirks too. [snip] I have used asyncio both the windows api and linux api version and have found them to be almost unusable and very, very, very difficult to get right. I very much aware of the utility of such a library to improve performance and to help properly factor and decouple i/o bottle necks from the rest of the application. I also believe that many users would find such a library very useful and would want to use it - if it were easy enough to use. This is the task of the library writer - to make the unusable usable.
You are already very mistaken in the premise for a library such as AFIO. Firstly, if you don't have a mission critical i/o bottleneck problem - one so serious that you are happy to throw your existing design and codebase out the door - then you don't need nor want async i/o. Modern kernels are truly excellent in hiding 80-90% of i/o bottlenecks for you with synchronous usage, and bypassing the kernel's algorithms and buffers so you can implement your own directly atop the physical hardware really is only for the serious performance hungry user. Most engineers will not design algorithms nor buffering systems which will beat those of the kernel except in specialised cases. This is your first misapprehension: async i/o is *supposed* to turn your application design on its head, and completely convolute everything in order to eke out that last bit of performance. What AFIO hopefully does is to hide a majority - not all - platform-specific quirks only. It intentionally does nothing, and nor should it, about the general design consequences of a fully asynchronous i/o based solution on your code. As much as that might appear to suck, and make the library unfriendly, well that's async i/o for you and that's why hedge funds pay $300/hour upwards to async i/o engineers because most engineers aren't wired that way, and those that are are especially rare.
so I would say you're not thinking big enough. if AFIO is not simple enough to be used within an hour of looking over the docs, it's too complicated.
Think bigger!!!!
What would be an ideal interface ? is there a way to implement it? For example:
main(..){
// example one asyncio::istream ais("filename"); // works almost like a stream int x; ais >> x; // read an x .... ais.sync()
:) Such a design would not make good use of hardware DMA such that use of the CPU can be completely avoided for bulk data transfers. To invoke hardware DMA, all i/o must be done from 4Kb aligned memory buffers. Indeed AFIO can enforce that for you because it's so important to performance. Generally if you're bothering to use async i/o, you have no interest in *ever* copying memory. That rules out all serialisation usually :) You've got to remember Robert that the user of async i/o will spend weeks squeezing microseconds of latency out of a routine whilst keeping stochastic variance within some bound. The Math guys here will know what I mean. If you don't need that kind of control, just go synchronous i/o, it's vastly easier.
// example two completion_function_object cfo = [](....); asyncio::istream ais("filename", cfo); ais >> x; // read an x, invoke cfo on completion
// example three - cfo is created as an io manipulator ais >> x >> cfo;
// example four - cfos and cfoy are created as io manipulators ais >> x >> cfox >> y >> cfoy; }
You can already schedule the invocation of completion callbacks using completion() or call(). However, something like the nice terse DSEL you just describe is coming eventually in Vicente's monadic continuations framework where one can schedule zero memory copying transfers of socket to disk in the same sequence of continuations. In other words, AFIO just "plugs in" seamlessly to what will hopefully become the standard C++ 17 way of doing async continuations for all C++ code. And that will be the more friendly way of programming AFIO such that all the usual boilerplate you need to write to get async libraries to interoperate goes away. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
Niall Douglas wrote
On 18 Aug 2014 at 9:54, Robert Ramey wrote:
OK - I'll try to figure out how to insert quoting.
I'll let you get the quoting reply thing working before I reply on that site. You made some excellent very valid points I will fix immediately, but many of them were answered in the docs already.
The only thing that the quoting is going to do is copy the previous post between <blockquote> tags. So I don't think this is a huge obstacle to replying. On the other hand, you've already replied here so there's no need at this point.
Where we diverge the most strongly is in what we think "easier" to mean. But I won't bother rehashing all that again.
OK
You are already very mistaken in the premise for a library such as AFIO.
All I did was follow a plain reading of the documentation. The typical C++ programmer should be able to get a more or less idea of what it is and how it works from such a reading. If he can't do this, then the library won't be widely used - if at all. If you want to avoid this, you'll have to do something differently.
so I would say you're not thinking big enough. if AFIO is not simple enough to be used within an hour of looking over the docs, it's too complicated.
Think bigger!!!!
What would be an ideal interface ? is there a way to implement it? For example:
main(..){
// example one asyncio::istream ais("filename"); // works almost like a stream int x; ais >> x; // read an x .... ais.sync()
Such a design would not make good use of hardware DMA such that ...
My view is that a) the above interface would be easy to understand. b) the above interface doesn't preclude any particular implementation and/or optimization at a lower level. The above is really a facade over some implementation. Of course, since I haven't actually implemented this - I could well be wrong that it would be doable. If it were doable, it would be a very popular boost library.
That rules out all serialisation usually :)
The serialization library depends on some stream or stream buffer implementation to do the i/o. It's possible to craft a standard stream buffer such that there would be no extraneous copies as part of the serialization. Basically the process of turning a data structure into a sequence of bytes is orthogonal to the process of actually doing any i/o. I hadn't thought about it, but a asyncio interface similar to the above would be a great complement to the serialization library and would even more popular for this reason. Anyway, I just read (some of) the documentation and logged my experience with it. I hope it can useful in some way. Good luck with this. Robert Ramey -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 19 Aug 2014 at 9:37, Robert Ramey wrote:
Such a design would not make good use of hardware DMA such that ...
My view is that a) the above interface would be easy to understand. b) the above interface doesn't preclude any particular implementation and/or optimization at a lower level. The above is really a facade over some implementation.
And, as I have mentioned many times now, such an easy to use upper
fascade is coming with the monadic continuations framework based
around expected
That rules out all serialisation usually :)
The serialization library depends on some stream or stream buffer implementation to do the i/o. It's possible to craft a standard stream buffer such that there would be no extraneous copies as part of the serialization. Basically the process of turning a data structure into a sequence of bytes is orthogonal to the process of actually doing any i/o. I hadn't thought about it, but a asyncio interface similar to the above would be a great complement to the serialization library and would even more popular for this reason.
I really don't think you fully understand what async i/o means to design, but perhaps I can help. What async i/o means to deserialisation is this: there are no current file pointers, and there are no guarantees that data is read consecutively. Indeed, when you read a 1Mb file, you see individual 0.5Kb/4Kb/64Kb sized chunks from *anywhere* in the file extent randomly appear into memory in a random order. These chunks are just as likely to appear at the end as at the beginning or anywhere else, and it is not just expected but known that gaps between consecutive pieces may exist for extended periods of time. Your code now has a choice: you can either block on missing chunks until they appear, which is equal and equivalent to using a memory mapped file - in which case, you should be using a memory mapped file instead and save yourself the hassle. Or you process individual fragments and regions as soon as enough of them appear into memory, and join up those parts as it becomes possible. If you think this through, you realise that your serialisation format must now be very different. Firstly, you need metadata of which regions of the serialised format can be processed individually, and that needs to be loaded completely before all else. Secondly, you must serialise into a recursive descent format, because you are going to be deserialising from the inside outwards - XML is an excellent example of a format well suited to asynchronous i/o based parsing, but almost any format /can/ be stored in a recursive descent format e.g. images. My point is that a linear serialisation format doesn't suit asynchronous i/o, and you shouldn't bother with async i/o with a linear serialisation format as the benefits aren't worth the considerable hassle. Does this make more sense?
Anyway, I just read (some of) the documentation and logged my experience with it. I hope it can useful in some way.
It's very useful. You're helping me understand where other engineers are finding trouble in making sense of me. Please keep going. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
-----Original Message----- From: Boost [mailto:boost-bounces@lists.boost.org] On Behalf Of Robert Ramey Sent: 18 August 2014 02:33 To: boost@lists.boost.org Subject: Re: [boost] [Concepts] Definition. Was [GSoC] [Boost.Hana] Formal review request
With an eye to verifying the existence of library using templates which would not benefit from explicit type constraints I went through some of the documentation of AFIO. I posted a log of my notes as I went through it here:
http://rrsd.com/blincubator.com/open-content/#comment-26
Of necessity, it sort of rambles around before it gets to the main point. That's because I had to start at the beginning in order to have enough context to understand it.
Short version
a) I don't think this library demonstrates that type constraints wouldn't help. In fact I think the opposite. b) This further reinforces my view that DOxygen is not a great system for writing C++ documentation. c) AFIO is much more complicated than I think it has to be - but I can't prove
this
because its so hard to understand anything about it. Sent from the Boost - Dev mailing list archive at Nabble.com.
I had a quite different reaction while skimming these docs. It looks jolly nice ;-) It certainly looked pretty complicated - but sadly these things often are :-( I'd have put the rationale after the intro, but that's a very minor thing - you can skip over by one click. I found it easy to find what template parameters were supposed to be and do by using the C++ reference section. (Though I didn't feel the across-the-page layout made it any easier to find the item of interest). And I've like an old-fashioned alphabetic index at the end, in case I know what I was looking for. It did provide more than I probably wanted to know about some things that one might consider implementation details, but sometimes that detail is useful to understanding and for a review may be important, so it may be useful to able to navigate around the details. There is method of controlling what is visible and what is hidden (Doxygen \cond ... \endcode) and after a review, this might be worth the effort. What I take away is that: * There is no pleasing everyone all the time :-( * The format that you propose is OK for STL-like stuff, whose interface is almost trivial by comparison with this (but whose under-the-hood is deceptively complex). * But when things get complicated, it isn't enough for the job, and Doxygen is better that anything else I've yet seen. * Providing the parameter info in the Doxygen syntax has the potential to using other tools to process and display in other ways in future. * Using Doxygen to generate a C++ reference section from the main body Quickbook avoids that delusion that feeding your code into Doxygen will document it. It and Quickbook both allow you to provide lots of links to the class parameters easily, very helpful to navigate when things get complicated. * If Doxygen doesn't handle the constraints on type parameters (AKA concepts?) well, then I am fairly confident that we can get it enhanced to do this. My 2 penceworth. Paul --- Paul A. Bristow Prizet Farmhouse Kendal UK LA8 8AB +44 (0) 1539 561830
On August 15, 2014 12:57:48 PM EDT, Niall Douglas
On 14 Aug 2014 at 8:45, Robert Ramey wrote:
Anyway, if I feel that bad template parameters would generate unhelpful error messages, I'll usually throw in some sort of clarifying static_assert like the above. I view these as very similar to C-style asserts - there to be useful during development, not as parameter constraints. [snip] Eventually the penny dropped and I got the documentation fixed up. I never did go back and change the static asserts. They're not wrong - but having them directly relatable to
Niall Douglas wrote the explicit concepts in the documentation would have made them less ad hoc. Also, it would have made explicit a bunch of underlying assumptions in the code. It would have made me see that I had several similar ideas which could have been consolidated. In short it would have given me a framework for making simple, more understandable and less incorrect code and avoided some asymmetries which haunt the code to this day. Maintaining backward archive capability would mean a lot more work to make these changes today.
I think this is the crux of our difference. You believe that type constraints are a good thing, and that structures of constrained type relations build meaning and enables better communication in documentation.
I on the other hand believe that type constraints pre-Concepts-Lite are a bad thing, and I wish the compiler wasn't so stupid - moreover, I know the compiler soon won't be so stupid. I see them as input sanitisers as a necessary evil, and they at best might be occasionally useful but generally they just get in the way and make code brittle both now and in the future. Hence they get used as sparingly as possible in assertion checks. I obviously use them extensively in metaprogramming, but that's constraining /selection/ of implementation which is opposite to sanitising inputs.
Setting aside your bias against type constraints, explain how a static_assert* in a class or function template, to ensure the parameterizing type meets the syntactic requirements, is a bad thing. Using them prevents template backtrace spew from the compiler which I see as good. *Boost.Concept Checking Library is just a fancy version of static_assert. ___ Rob (Sent from my portable computation engine)
I on the other hand believe that type constraints pre-Concepts-Lite are a bad thing, and I wish the compiler wasn't so stupid - moreover, I know the compiler soon won't be so stupid.
Type constraints in C++ work the same way, currently, as they will when Concepts Lites arrive(with the exception of specializations vs overloading). If you believe type constraints are bad in pre-Concepts Lite, then the arrival of Concepts Lite won't change your opinion on type constraints. Concept Lites are not some silver bullet that will make libraries have clean error messages and fast compiles. The truth is, the type requirements need to be specified, and library writers need to think about these type requirements, document them, and check they are fulfilled using either Boost.ConceptCheck, SFINAE type traits, or in the future `concept bool`(ie Concepts Lite). Paul Fultz II -- View this message in context: http://boost.2283326.n4.nabble.com/Concepts-Definition-Was-GSoC-Boost-Hana-F... Sent from the Boost - Dev mailing list archive at Nabble.com.
2. Unless there are reasons to do otherwise, such library should attempt to issue a diagnostic message during compilation that the requirements on types have not been satisfied. This doesn't need to be Boost.ConceptCheck (if no consensus can be reached on using it). Probably a static assert with a type trait should be enough:
template<class T> quick_sort(iterator<T> begin, iterator<T> end) { static_assert(is_less_than_comparable<T>::value, "T is not LessThanComparable"); static_assert(is_swappable<T>::value, "T is not Swappable"); // do the work }
Not an ideal, but perhaps less controversial.
If traits are going to be used, then `enable_if` should really be used
instead. This allows for better reusability. Say for instance I want a trait
that checks if the type is quick sortable:
template<class T>
struct holder { typedef void type; }
template
On 13 Aug 2014 at 23:00, Robert Ramey wrote:
Niall Douglas wrote
So tl;dr; I am really saying the time for concepts - whatever they are to whoever's definition - isn't here yet.
I would disagree.
We know.
The whole STL library is based on "concepts". That is, all template parameter have explicit requirements. This is true now and has always been so.
No Robert, they do not. STL template parameters have informal tacit requirements based on convention. If a template parameter is called InputIterator, that implies how it's going to be used. Little explicit enforcement is done past that point, and that's a good thing.
Let's get a few concept programming libraries based on a Concepts Lite compiler around first. Let's not dig ourselves now into a straightjacket we later regret.
Concepts lite is not really relevant here. It won't change the landscape in any way.
This is a spurious claim. Not only can you simply not claim this because you don't know the future any more than I do, but the authors of Concepts Lite would disagree with you severely. Concepts Lite provides orders of magntitute efficiency improvements to type constraint programming. That surely will yield orders of magnitude more complexity in their use as we programmers like to use as much rope as is given. We simply don't know what form that will take yet, students like Louis will show us old timers just how much we didn't know.
Library authors aren't failing to explicitly define and enforce their type requirements because they lack compiler support for this. They're doing it because we don't demand that we do so.
I don't see any benefit to bringing in extra brittleness where it isn't needed. That implies the library writer preempting what users will think of doing with the library. That's a big no no for any good library design, library code is supposed to be used in surprising new ways, that's why it's a library rather than fragments of copy and paste bits. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
-----Original Message----- From: Boost [mailto:boost-bounces@lists.boost.org] On Behalf Of Roland Bock Sent: 05 August 2014 22:37 To: boost@lists.boost.org Subject: Re: [boost] [Concepts] Definition. Was [GSoC] [Boost.Hana] Formal review request
It's somewhat off topic, but I'm going to take the opportunity to point out https://www.sgi.com/tech/stl/doc_introduction.html . I've come to believe that C++ libraries - in particular parameterized types, are best described by the documentation approach embodied in this link. It is sufficiently formal where it has to be - but not so formal
that one
gets too bogged down.
I've made a big point of this inhttp://rrsd.com/blincubator.com/requirements_documentation/ . My criticism of the HANA documentation is really that it fails to follow this format and content.
I haven't read enough documentation on Hana to comment on that, but I agree in principle that uniformity, consistency, use of concepts etc are extremely useful to enhance documentation. I have my doubts though, that the STL documentation structure can be used as-is in a reasonable way for every library.
For instance I would not know how to do that for sqlpp11, but I would love to discuss it over a beer at CppCon.
I've already said the same for other libraries documentation. IMO the STL docs structure doesn't work well for anything but trivially (but invaluable) small libraries. It's the lack of hyperlinks and indexing - the "how do I find what I want to know when I'm not even sure yet what I want is called?" problem. People get obsessed with the look rather than how documentation works. We haven't cracked this yet. Paul --- Paul A. Bristow Prizet Farmhouse Kendal UK LA8 8AB +44 (0) 1539 561830
participants (14)
-
Andrzej Krzemienski
-
Ingo Loehken
-
Krzysztof Czainski
-
Marc Glisse
-
Michael Levine
-
Michael Shepanski
-
Mostafa
-
Niall Douglas
-
Paul A. Bristow
-
pfultz2
-
Rob Stewart
-
Robert Ramey
-
Roland Bock
-
Steve M. Robbins