
"Robert Ramey" <ramey@rrsd.com> writes:
David Abrahams wrote:
The point is that if one writes a program in accordance with the requirements stated here, the program will be a legal program and will compile.
But that's not enough. I'm not interested in making an archive that just compiles; I want it to have some sensible semantics. What requirements do I have to fulfill in order to make the archive actually *work*?
If you look at the iterator requirements, for example, you'll see that there are semantic requirements in place, not just syntactic ones. These requirements are needed so that the algorithms can say something about what they do. The sort() algorithm wouldn't be able to make any claims about its result if writing into a random access iterator were allowed to be a no-op.
I can see that, but then one has an ostream_iterator which is a forward iterator.
No, it's an output iterator.
It does something quite different from other forward iterators such as one associated with a std::list.
No surprise, since it's not a forward iterator. It doesn't need to meet the semantic guarantees of forward iterator. It still meets the semantic guarantees of output iterator.
I'm sure I could dig up other examples. I really did think about what one should say about the sematics. And when I considered possibilities like an archive used for data logging, it seemed that there was less and less I could say about the semantics without saying something incorrect. So I moved to saying as little as possible.
As I've said, that's not very useful.
Of course, I would expect all archive implementations to call "serialize" but maybe someone comes up with an archive implementation that just checks syntax or something like that. Someone might want to make an archive which only stored/loaded primitive types. Or someone might make an archive that was implemented solely in terms of save/load_binary. These would never call serialize.
Do not build in generality that you're not even sure is needed, especially if it costs you your ability to write concepts that tell people how to get sensible results. You can always introduce less-refined concepts that allow these kinds of things and provide weaker semantic guarantees.
My thought was not to build in any requirement that wasn't necessary.
Those requirements _are_ necessary if you want loading and saving to do anything reasonable.
Common Type Definitions in all Archives
This should be a section for the "Archive" concept.
That was my intention. I didn't make a subtitle "Archive Concept" because I already had the chapter titled "Archive Concept"
Call the chapter "Archive Concepts," then.
OK what I meant to say is
A boolean MPL Integral Constant for which the following expression is true
boost::mpl::is_equal< A::is_loading, boost::mpl::bool_<true>
<snip>
How would you suggest I phrase this?
I believe that requirement is too strong, and it would be sufficient to say
An MPL Integral Constant with a nonzero ::value member
So if somewhere in the implementation I use:
boost::mpl::is_equal< A::is_loading, boost::mpl::bool_<true>
I don't know why you would ever do that when you could just use A::is_loading directly, and there is no mpl::is_equal. I assume you mean equal_to.
but the archive has A::is_loading defined as boost::mpl::int_<4> it will still work? If you say its true, I don't doubt it. But I would have hoped for a compile time error here.
In that case http://www.boost.org/libs/mpl/doc/refmanual/equal-to.html are pretty clear on semantics; you can look this up as easily as I can. If you really want to use that test you have to say An MPL Integral Constant with a ::value member equal to true
register_type is not a member function but a member function template. A template is not a function.
I could change the heading to "Common Operations for all Archives" or .. your suggestion here.
The heading should be "Archive Concept Requirements" with a note that each entry describes an expression that must be valid.
How about just "Requirements" as its already part of a section titled "Saving Archive (Concept)"?
Well, as you have pointed out, register_type is required for loading archives too.
Also, I just noticed "along with other information." If I'm writing an archive, how am I supposed to fulfill that requirement? Can I write any arbitrary "other information" I want? Suppose I write a zero-valued char? Suppose I don't write _any_ "other information?"
This "other information" is an implementation detail of the particular archive class.
Then it's not a requirement, right?
The user of any archive implementing the concept doesn't have to know what other information is in the archive.
Irrelevant.
I do believe I'm begining to see what the origin of this problem is. I'll address it below after a few details are out of the way.
You should leave out "template." This is a little tricky, but that expression will never be valid in a context where A is not a dependent type. I realize you do need it when A is a dependent type, but the convention is to use the simpler notation.
Hmm - all Archives included with the library are templates.
Irrelevant.
And incorrect AFAICT. http://www.boost.org/libs/serialization/doc/archives.html#archive_models shows a bunch of non-template archive models, doesn't it? Oh, no it doesn't, those are just freestanding constructor signatures, which would be invalid if written that way. Ugh. Okay, so...
So, removing this will be including a "valid expression" which will fail to compile on all conforming compilers.
No.
some_archive_template<Whatever> ar; ar.template register_type<T>();
is ill-formed.
some_archive_template<Whatever> ar; ar.register_type<T>();
is well-formed if T is a type and Whatever is a valid template argument to some_archive_template.
I don't see this. I am looking at Appendix C.13.6 of The C++ Programming Language by Stroustrup page 858. It seems that he has our exact example there:
<begin quote> class Memory { public: template<class T> T* get_new(); ... };
template<class Allocator> void f(Allocator & m){ int * p1 = m.get_new<int>(); // syntax error: int after less-than operator int * p2 = m.template get_new<int>(); // explicit qualification ... }
That's a context in which Allocator is a dependent type. Let me be perfectly clear. Try compiling this: struct foo {}; void f() { boost::serialization::text_oarchive<std::ofstream> ar; ar.template register_type<foo>(); } On a conforming compiler, it will fail. Now remove the template keyword and try again.
I find this rather alarming. Haven't I made it abundantly clear that the concept documentation has to give at least a minimal and complete documentation of what's required of an Archive?
I don't believe anything so far conflicts with that.
Maybe I've been too hasty, but it seemed to me, from the lack of any requirement that the archive do something that interacts with the Serializable concept (and produce sensible semantics) and your reference to a separate section describing how to implement an archive, that you had been trying to make the "Archive Concept" section a "user-only" document, and had put the real requirements elsewhere.
correct. But I didn't think of them as "real requirements", I thought of them as "implementation details" from the perspective of the user.
Are they requirements or aren't they? It would be conceptually purer if a model of the Archive concept wasn't required to be derived from a library-provided class template, but I could live with that derivation requirement if the other requirements you specified were complete and meaningful.
An algebra's semantic rules describe invariants. The meanings of statements in an algebra is constrained their invariant transformations.
a = b ==> b = a
is semantic.
As much as I'd like to respond to that it would lead us too far astray
Good; I don't want to talk about algebras anyway.
It's not formality that's the problem: it's vagueness, inconsistency, and lack of a practical document that describes what an archive implementor needs to do.
Maybe - But I haven't yet heard from anyone who wants to do this but failed because of this.
Matthias did. He only succeeded after getting information from you that wasn't present in the docs.
I think what I should have done and what we should do now is:
a) change the title of the section "Archive Concept" back to "Archive User Interface" or "Archive Interface". and restore the original content which is based of function prototypes. b) change the title of the section titled "Serializable Concept" back to "Serializable types". c) The question of formal documentation for the serialization library can be considered at leisure.
Grrr! You're very close to having reasonable concept documentation now; I don't know why you'd throw that out. As I've said, "formal" documentation isn't the issue; the question is whether the docs can be practically used by someone who wants to build a new archive type. -- Dave Abrahams Boost Consulting www.boost-consulting.com