
Hi, I've spotted some problems when playing with BCCL: - The implementation of assignable_archetype defines private default and copy constructors, so for example assignable_archetype<copy_constructible_archetype<>> will not actually be copy constructible. The same for convertible_to_archetype and convertible_from_archetype, but additionally with copy assignment. Is this by purpose? - copy_constructible_archetype defines public default constructor - again, am I overlooking something or it should not be there? - Function and predicate archetypes also seem to provide too wide interface (they are copy constructible and assignable). Additionally, they don't allow for archetypes chaining since they lack the Base parameter (with the only exception of binary_predicate_archetype - why the inconsistency?) - Apart from the provided function object concepts and archetypes it seems it would be useful to have a general Callable concept and the corresponding callable_archetype, parameterised with the types of arguments and return value. Wouldn't it be valuable to add them? - There's boost/concept_check directory in the trunk - are the files in it actually used anywhere? I've found no reference to them in Boost headers, documentation doesn't mention them too. Best regards, Robert

Robert Kawulak wrote:
I've spotted some problems when playing with BCCL:
- The implementation of assignable_archetype defines private default and copy constructors, so for example assignable_archetype<copy_constructible_archetype<>> will not actually be copy constructible. The same for convertible_to_archetype and convertible_from_archetype, but additionally with copy assignment. Is this by purpose?
I should think that's by design. The archetypes are to validate a particular concept checking class, so a copyable or default constructible archetype for Assignable would be wrong. Are archetypes are supposed to be composable? Even if so, not all combinations are possible.
- copy_constructible_archetype defines public default constructor - again, am I overlooking something or it should not be there?
I wouldn't think so.
- Function and predicate archetypes also seem to provide too wide interface (they are copy constructible and assignable).
Since you're asking, and I haven't checked to verify it, I presume that those operations are not part of the corresponding concepts. If so, then I agree they should not be available.
Additionally, they don't allow for archetypes chaining since they lack the Base parameter (with the only exception of binary_predicate_archetype - why the inconsistency?)
Are they supposed to be generally chainable?
- Apart from the provided function object concepts and archetypes it seems it would be useful to have a general Callable concept and the corresponding callable_archetype, parameterised with the types of arguments and return value. Wouldn't it be valuable to add them?
That seems plausible and useful. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com ________________________________ IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

From: Stewart, Robert
- The implementation of assignable_archetype defines private default and copy constructors, so for example assignable_archetype<copy_constructible_archetype<>> will not actually be copy constructible. The same for convertible_to_archetype and convertible_from_archetype, but additionally with copy assignment. Is this by purpose?
I should think that's by design. The archetypes are to validate a particular concept checking class, so a copyable or default constructible archetype for Assignable would be wrong.
I wouldn't say it's wrong. If you can combine several concepts, you should be able to combine the corresponding archetypes too. If your template requires more than one concept (e.g., a type that is BOTH copyable AND assignable), then without the ability of chaining you would have to write your own archetypes in all but the most trivial cases.
Are archetypes are supposed to be composable?
I guess they are since most of them have the Base template parameter.
Even if so, not all combinations are possible.
Could you give an example of an impossible combination?
- copy_constructible_archetype defines public default constructor - again, am I overlooking something or it should not be there?
I wouldn't think so.
- Function and predicate archetypes also seem to provide too wide interface (they are copy constructible and assignable).
Since you're asking, and I haven't checked to verify it, I presume that those operations are not part of the corresponding concepts. If so, then I agree they should not be available.
What should be done about this, then? Removing the superfluous functions may break some tests, but I guess in this case it is even desirable because it means the tests have errors that were undetected so far. I don't know why a valid test would depend on a function that should not be a member of an archetype.
Additionally, they don't allow for archetypes chaining since they lack the Base parameter (with the only exception of binary_predicate_archetype - why the inconsistency?)
Are they supposed to be generally chainable?
Actually I also wasn't sure before I wrote my previous mail and to verify this I've written my own set of archetypes to test my library. They look similarly to the ones in concept_archetype.hpp modulo all the issues I've mentioned. They also don't provide any function implementations, only declarations[*]. They seem to work fine with chaining. The only two restrictions are: - default_constructible_archetype must be on top of any other archetypes that have any constructors (otherwise the constructors of the derived archetype would prevent generation of default constructor), - convertible_from_archetype must be the top-most archetype of all chained archetypes (because constructors aren't inherited). Note that there are no such problems with copy_constructible_archetype and assignable_archetype because the functions are always generated automatically (unless the base class doesn't have them or makes them inaccessible - but no other archetype than the two should have them and the only one that makes them inaccessible is null_archetype, which is always at the end of the chain). [*] Why the implementations are provided in concept_archetype.hpp, BTW? Are there cases where concept checking programs should be linked, not only compiled?
- Apart from the provided function object concepts and archetypes it seems it would be useful to have a general Callable concept and the corresponding callable_archetype, parameterised with the types of arguments and return value. Wouldn't it be valuable to add them?
That seems plausible and useful.
Other things I miss are: separation of predicate_archetype from const_predicate_archetype etc. (currently implementation of the former is actually the latter) and not requiring const arguments in *_function_archetype (the constness can be expressed in the template argument if needed). Best regards, Robert

Robert Kawulak wrote:
From: Stewart, Robert
- The implementation of assignable_archetype defines private default and copy constructors, so for example assignable_archetype<copy_constructible_archetype<>> will not actually be copy constructible. The same for convertible_to_archetype and convertible_from_archetype, but additionally with copy assignment. Is this by purpose?
I should think that's by design. The archetypes are to validate a particular concept checking class, so a copyable or default constructible archetype for Assignable would be wrong.
I wouldn't say it's wrong. If you can combine several concepts, you should be able to combine the corresponding archetypes too. If your template requires more than one concept (e.g., a type that is BOTH copyable AND assignable), then without the ability of chaining you would have to write your own archetypes in all but the most trivial cases.
I would. The purpose of an Assignable archetype is to test that a type that is assignable, but possibly neither default nor copy constructible, satisfies the concept. That is, the Assignable concept checker should not impose *any* other criteria on its parameterizing type.
Are archetypes are supposed to be composable?
I guess they are since most of them have the Base template parameter.
OK
Even if so, not all combinations are possible.
Could you give an example of an impossible combination?
The OP's! Seriously, my point is that making a particular archetype restrict its interface might generally prevent certain combinations. In order to make the Assignable archetype neither default nor copy constructible, to ensure that the concept checker doesn't require those capabilities, it cannot be combined with CopyConstructible's or DefaultConstructible's archetypes, at least not as the derivate. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com ________________________________ IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

From: Stewart, Robert
- The implementation of assignable_archetype defines private default and copy constructors, so for example assignable_archetype<copy_constructible_archetype<>> will not actually be copy constructible. The same for convertible_to_archetype and convertible_from_archetype, but additionally with copy assignment. Is this by purpose?
I should think that's by design. The archetypes are to validate a particular concept checking class, so a copyable or default constructible archetype for Assignable would be wrong.
I wouldn't say it's wrong. If you can combine several concepts, you should be able to combine the corresponding archetypes too. If your template requires more than one concept (e.g., a type that is BOTH copyable AND assignable), then without the ability of chaining you would have to write your own archetypes in all but the most trivial cases.
I would. The purpose of an Assignable archetype is to test that a type that is assignable, but possibly neither default nor copy constructible, satisfies the concept. That is, the Assignable concept checker should not impose *any* other criteria on its parameterizing type.
I guess you could've misunderstood what I ask for - it's not making the extra special functions public but rather removing them completely. This allows for composition while still it's not making the archetypes looser than required. The actual code I use is: template <typename T = int> class null_archetype { null_archetype(); null_archetype(const null_archetype &); null_archetype & operator = (const null_archetype &); ~null_archetype(); }; template < typename Base = null_archetype<> > struct copy_constructible_archetype : public Base { copy_constructible_archetype(const copy_constructible_archetype &); ~copy_constructible_archetype(); }; template < typename Base = null_archetype<> > struct assignable_archetype : public Base { assignable_archetype & operator = (const assignable_archetype &); }; How is assignable_archetype<> default or copy constructible now? It's not unless you combine it - for example only assignable_archetype<copy_constructible_archetype<>> is both assignable and copy constructible. In comparison, the current implementation of the classes is: template <class T = int> class null_archetype { private: null_archetype() { } null_archetype(const null_archetype&) { } null_archetype& operator=(const null_archetype&) { return *this; } public: null_archetype(detail::dummy_constructor) { } }; template <class Base = null_archetype<> > class copy_constructible_archetype : public Base { public: copy_constructible_archetype() : Base(static_object<detail::dummy_constructor>::get()) { } copy_constructible_archetype(const copy_constructible_archetype&) : Base(static_object<detail::dummy_constructor>::get()) { } copy_constructible_archetype(detail::dummy_constructor x) : Base(x) { } }; template <class Base = null_archetype<> > class assignable_archetype : public Base { assignable_archetype() { } assignable_archetype(const assignable_archetype&) { } public: assignable_archetype& operator=(const assignable_archetype&) { return *this; } assignable_archetype(detail::dummy_constructor x) : Base(x) { } }; Now: - assignable_archetype<copy_constructible_archetype<>> is not copy constructible, - assignable_archetype<default_constructible_archetype<>> is not default constructible, - copy_constructible_archetype<> is also default constructible, - assignable_archetype<> is also destructible (which it doesn't necessarily have to be). Either I'm overlooking something or the current implementation is simply wrong and needs to be fixed.
Even if so, not all combinations are possible.
Could you give an example of an impossible combination?
The OP's! Seriously, my point is that making a particular archetype restrict its interface might generally prevent certain combinations.
But why you'd want to prevent certain combinations at all? Is there anything wrong with combining archetypes? If not, than an archetype doesn't have to (and shouldn't) restrict its interface (by "restricting" I don't mean "not providing", but "prevent from providing by combined archetypes"). Assuming you use null_archetype as the root base class, you don't need to restrict anything because it is sufficient not to declare functions that are not needed. They will not be provided unless you chain the archetype with another archetype that provides them. OTOH, restricting them will practically break chaining (as it does now).
In order to make the Assignable archetype neither default nor copy constructible, to ensure that the concept checker doesn't require those capabilities, it cannot be combined with CopyConstructible's or DefaultConstructible's archetypes, at least not as the derivate.
Sorry, but could you give a code example? I still don't see your point. assignable_archetype<> defined as above is not copy nor default constructible. assignable_archetype<default_constructible_archetype<copy_constructible_arch etype<>>> is. Do you mean that chaining archetypes like this should be forbidden? If so, why? After all, if you can combine concepts, you must be able to combine archetypes as well or otherwise you're not able to test the concepts at all. For example, if you have a function template: template<typename T> void f(const T &) { BOOST_CONCEPT_ASSERT((Assignable<T>)); BOOST_CONCEPT_ASSERT((CopyConstructible<T>)); ... } Then how do you test this function without chaining? You have to write your own simple archetype that combines assignable_archetype<> and copy_constructible_archetype<>. I don't see any point in doing this repetitive and error-prone work when you could simply use assignable_archetype<copy_constructible_archetype<>>. Best regards, Robert

Robert Kawulak wrote:
From: Stewart, Robert
The purpose of an Assignable archetype is to test that a type that is assignable, but possibly neither default nor copy constructible, satisfies the concept. That is, the Assignable concept checker should not impose *any* other criteria on its parameterizing type.
I guess you could've misunderstood what I ask for - it's not making the extra special functions public but rather removing them completely. This allows for composition while still it's not making the archetypes looser than required.
That leaves them for the compiler to generate. The generated special functions will be public, unless you suppress them otherwise, so the archetype would be looser than it should be. Am I speaking from ignorance of the actual classes in BCCL?
The actual code I use is:
template <typename T = int> class null_archetype { null_archetype(); null_archetype(const null_archetype &); null_archetype & operator = (const null_archetype &); ~null_archetype(); };
template < typename Base = null_archetype<> > struct copy_constructible_archetype : public Base { copy_constructible_archetype( const copy_constructible_archetype &); ~copy_constructible_archetype(); };
template < typename Base = null_archetype<> > struct assignable_archetype : public Base { assignable_archetype & operator = ( const assignable_archetype &); };
How is assignable_archetype<> default or copy constructible now? It's not unless you combine it - for example only assignable_archetype<copy_constructible_archetype<>> is both assignable and copy constructible.
Ah, here you've suppressed the compiler's ability to generate a default constructor, copy constructor, or copy assignment operator because the corresponding special functions are private in the base. Nice.
In comparison, the current implementation of the classes is:
template <class T = int> class null_archetype { private: null_archetype() { } null_archetype(const null_archetype&) { } null_archetype& operator=(const null_archetype&) { return *this; } public: null_archetype(detail::dummy_constructor) { } };
template <class Base = null_archetype<> > class copy_constructible_archetype : public Base { public: copy_constructible_archetype() : Base(static_object<detail::dummy_constructor>::get()) { } copy_constructible_archetype(const copy_constructible_archetype&) : Base(static_object<detail::dummy_constructor>::get()) { } copy_constructible_archetype(detail::dummy_constructor x) : Base(x) { } };
template <class Base = null_archetype<> > class assignable_archetype : public Base { assignable_archetype() { } assignable_archetype(const assignable_archetype&) { } public: assignable_archetype& operator=(const assignable_archetype&) { return *this; } assignable_archetype(detail::dummy_constructor x) : Base(x) { } };
Now: - assignable_archetype<copy_constructible_archetype<>> is not copy constructible, - assignable_archetype<default_constructible_archetype<>> is not default constructible, - copy_constructible_archetype<> is also default constructible, - assignable_archetype<> is also destructible (which it doesn't necessarily have to be).
Either I'm overlooking something or the current implementation is simply wrong and needs to be fixed.
We may be overlooking some special cases the authors were accounting for, but it seems to me your proposal is sound.
Even if so, not all combinations are possible.
Could you give an example of an impossible combination?
The OP's! Seriously, my point is that making a particular archetype restrict its interface might generally prevent certain combinations.
But why you'd want to prevent certain combinations at all?
Because doing so produced bad results, though it appears that result is not necessary.
Is there anything wrong with combining archetypes?
No, not if doing so does the right thing. Any implementation should strive to disable invalid combinations, even if invalid solely because of language or implementation limitations.
In order to make the Assignable archetype neither default nor copy constructible, to ensure that the concept checker doesn't require those capabilities, it cannot be combined with CopyConstructible's or DefaultConstructible's archetypes, at least not as the derivate.
Sorry, but could you give a code example? I still don't see your point.
Obviously, I was arguing WRT the current implementation, not to one you had not yet shown and I didn't understand you to be proposing. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com ________________________________ IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

From: Stewart, Robert Ah, here you've suppressed the compiler's ability to generate a default constructor, copy constructor, or copy assignment operator because the corresponding special functions are private in the base. Nice.
Actually, this is how it's already done in the current implementation too.
Is there anything wrong with combining archetypes?
No, not if doing so does the right thing. Any implementation should strive to disable invalid combinations, even if invalid solely because of language or implementation limitations.
OK, but can you name such an invalid combination? I'm asking just out of curiosity because I can't think of such a combination right now.
Sorry, but could you give a code example? I still don't see your point.
Obviously, I was arguing WRT the current implementation, not to one you had not yet shown and I didn't understand you to be proposing.
But my implementation doesn't differ from the current one in any significant way other than I've already explained (i.e., it removes the superfluous special members). Best regards, Robert

on Sat Dec 03 2011, Robert Kawulak <robert.kawulak-AT-gmail.com> wrote:
Either I'm overlooking something or the current implementation is simply wrong and needs to be fixed.
I think you're probably right, and I like your approach. I was the last person to do any serious work on BCCL (not on the archetype side of things) but there isn't really a regular maintainer. How would you like to take that job? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

From: Dave Abrahams I think you're probably right, and I like your approach. I was the last person to do any serious work on BCCL (not on the archetype side of things) but there isn't really a regular maintainer. How would you like to take that job?
Well, I see two problems with that. First, I can't promise to always be able to find time to address requests. Second is that I'm not familiar with most of the implementation and I wouldn't really feel confident making changes to it. Therefore I think it would be better if there's someone else on the list willing to take the maintainer's job. If not, however, I guess that me as the maintainer would still be better than no maintainer at all, so I might try and fix it here and there, asking for tolerance if I break something. BTW, does anybody know if Jeremy Siek - the author of the library - is still somewhere around? I'd feel much better if I could ask for rationale about why some things are the way they are. Best regards, Robert

on Mon Dec 19 2011, Robert Kawulak <robert.kawulak-AT-gmail.com> wrote:
From: Dave Abrahams
I think you're probably right, and I like your approach. I was the last person to do any serious work on BCCL (not on the archetype side of things) but there isn't really a regular maintainer. How would you like to take that job?
Well, I see two problems with that. First, I can't promise to always be able to find time to address requests.
Well, that's not exactly a step backwards from where we are now :-)
Second is that I'm not familiar with most of the implementation and I wouldn't really feel confident making changes to it.
That's why we have a test suite.
Therefore I think it would be better if there's someone else on the list willing to take the maintainer's job. If not, however, I guess that me as the maintainer would still be better than no maintainer at all, so I might try and fix it here and there, asking for tolerance if I break something.
That's the spirit!
BTW, does anybody know if Jeremy Siek - the author of the library - is still somewhere around? I'd feel much better if I could ask for rationale about why some things are the way they are.
He doesn't have much time for Boost these days but I'm sure he'd be willing to answer some questions. I've Cc'd him. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

on Fri Nov 25 2011, Robert Kawulak <robert.kawulak-AT-gmail.com> wrote:
From: Stewart, Robert
- The implementation of assignable_archetype defines private default and copy constructors, so for example assignable_archetype<copy_constructible_archetype<>> will not actually be copy constructible. The same for convertible_to_archetype and convertible_from_archetype, but additionally with copy assignment. Is this by purpose?
I should think that's by design. The archetypes are to validate a particular concept checking class, so a copyable or default constructible archetype for Assignable would be wrong.
I wouldn't say it's wrong. If you can combine several concepts, you should be able to combine the corresponding archetypes too. If your template requires more than one concept (e.g., a type that is BOTH copyable AND assignable), then without the ability of chaining you would have to write your own archetypes in all but the most trivial cases.
I think the problem is that C++03 doesn't let you define copyability and assignability "additively," and offers no way to detect those capabilities so we can decide not to subtract them. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (3)
-
Dave Abrahams
-
Robert Kawulak
-
Stewart, Robert