
"Robert Ramey" <ramey@rrsd.com> writes:
.>> 4. The documentation says that you can write your freestanding
serialize() function in namespace boost::serialization, with the strong implication that it will work even on compilers that support ADL. But it won't work unless boost::serialization is an associated namespace of one of the arguments, as demonstrated by the following program:
namespace me { class X {}; }
namespace boost { namespace serialization {
template <class T> int call_serialize(T const& x) { serialize(x); return 0; }
void serialize(me::X);
}}
int y = boost::serialization::call_serialize(me::X());
In case it wasn't 100% obvious, the above fails to compile on a conforming compiler.
Well it wasn't obvious to me. Its still not. It just compiled on my comeau 4.3 without error.
I always thought that compiler was conforming. Oh well.
On Windows? That's normally in "microsoft bug emulation mode." Try http://www.comeaucomputing.com/tryitout (I did!) I hate having to go crawling through the standard just to find this stuff, but for you, because I like you, kid, I make a special exception: 14.6.4 Dependent name resolution [temp.dep.res] In resolving dependent names, names from the following sources are considered: — Declarations that are visible at the point of definition of the template. — Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.6.4.1) and from the definition context. Unless one of the arguments has boost::serialization as an associated namespace, only the first bullet point applies in this case. It means that any overloads provided by the user after the call_serialize function definition has been seen will not be considered for overload resolution.
Maybe no one has every had an issue with this as it is customary and natural to declare and/or define the template
template<class Archive> void serialize(Archive &ar, me::X, const unsigned int version){ ... }
in the same header where X itself is declared and/or defined.
That's irrelevant to the problem, actually.
Also the body of the serialize function typically will refer only to member data and functions.
So? The problem happens during name lookup. If the user's serialize overload is never considered, it doesn't matter what gets put in its implementation.
But the truth is I would have to delve into this a lot deeper to see what's going on here.
Well, you'd better. The documentation as of now is not adequate to know how to write an archive that works with the serialization library.
As far as I can tell, there's no requirement that any of the arguments to serialize have boost::serialization as an associated namespace.
There isn't. And I don't think it's necessary. serialize(me::X) is only called from within the namespace boost::serialization never from anywhere out side this namespace. Hence, the serialize function is found according to the rules of ordinary lookup.
No, not in the example above it isn't, because serialize follows the definition of call_serialize.
As above its not clear to me that anyone ever does this.
?? #include <boost/serialization/header-containing-call_serialize.hpp> #include "mytype-and-its-serialize-function.hpp" is all it takes.
The set of candidates that can be found by ordinary lookup is fixed at the template's point of definition.
You have introduced yet another header order dependency here. You don't need to experience the wailing and gnashing of teeth associated with that problem again, do you?
I'm getting used to it.
Please, don't get used to it! If your tolerance for it goes up any further nobody will be able to convince you to fix anything! ;-)
Actually this would be much worse than the one before. In my other infamous case, at least the compiler threw and #error when the rule was violated. With two-phase lookup, the compiler silently changes the program semantics when header order is changed.
It's not two-phase lookup that's the culprit, it's incorrect instructions about how to customize the serialize() functionality.
If one's compiler supports ADL, then he can use a free function in namespaces associated with the type being serialized. But it's not a requirement
I beg to differ. And the docs make it sound as though putting the functions in boost::serialization is the more portable of the two options.
Hmm - if one puts in the boost::serialization namespace it works except mayb in cases such as that above.
?? It fails unless one of the arguments to serialize has boost::serialization as an associated namespace. That's
Its not clear to me that that is not a contived example which never ^^^^ what is "that?" happens in practice.
If one puts in the namespace of the class being serialized - it depends upon ADL to function. So my view is that putting it into boost::serialization is more portable.
Even if that were true in practice, you can't recommend a practice that doesn't work on a conforming compiler as the more portable of the two, at least not without a big caveat that it relies on nonportable techniques... can you?!
In reality I suspect its not such an issue these days as most compilers seem to support ADL.
I concede I've struggled with two-phase lookup and ADL so I'm willing to be shown to be wrong about this.
The example above demonstrates.
Hmm - I'm not convinced yet.
The online compiler demonstrates.
Yes, I understand what the intent is. Actually, there is precedent for what you're trying to do, sorta. The Indiana proposal for concepts in C++0x (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1849.pdf) uses something called a "pseudo-signature" that looks very much like what you've written. However, there are special rules for reading and understanding pseudo-signatures. One way to make your specification formally complete would be to make sure that, when expressed according to the rules in that proposal, it says what you mean it to say. Then you can reference the proposal in the docs in case someone wants to understand the requirements on a formal level.
Well, I didn't know about this. But your explanation doesn't make sound very easy to understand or use.
Very well, then, if you don't like that, use the "traditional" table of valid expressions, etc.
What about the names of function and member template parameters?
What about about them? What is the question here?
Do I have to use the same names as you do in your example?
I know the answer to that one, but a novice might not.
What is the answer?
No.
Maybe. It's certainly not complete enough for someone like me to be sure of what it really means.
<referring to the SGI STL docs>
:) I'm using it on some slides now and discovering just how many holes, anachronisms, and inaccuracies there are in it. Still, the basic approach is a good one.
I don't actually think Bill Kempf's format results in particularly good docs. I used that approach for Boost.Python's reference and now I wish I hadn't. I think the Parameter library (admittedly much smaller) is much better.
Then someone should update those pages.
Or replace them.
I've strived to do things in the "boost" way to maximize the mental leverage to be gained from using an established pattern. If we should use them we should have another model.
Feel free to propose one.
BTW, updating these pages ain't going to be that easy. Traditionally, C/C++ programs were fairly easy to describe with an interface for each class along with notes regarding implementation semantics. Now with both class and function templates the old patterns are not enough. I look forward to seeing this improved.
Me too. <taps foot expectantly>
Another great idea would be to tie concept checking into the "formal" template documentation so that the code checks the documentation. A way too ambitious idea but fun to consider.
Already in the pipeline, believe it or not.
As I said, I see this implementation section as a means to fullfilling the basic requirement not as new requirements.
You said that? Where?
Reference/Archive Class Reference/Implementation states in its opening paragraph:
The Archive concept specifies the functions that a class must implement to in order to be used to serialize Serializable types. The library implements a family of archives appropriate for different purposes. This section describes how they have been implemented and how one can implement his own archive class.
That seems pretty clear to me that the are archives included model he Archive concept. It would be easy to add that sentence
Sorry, I can't understand anything you're trying to tell me in the whole quoted section above, so I don't know if it would help. -- Dave Abrahams Boost Consulting www.boost-consulting.com