[this is a repost - no idea what happened to the first version, maybe its still floating around gmane somewhere - sorry in advance if this appears twice] Peter Dimov wrote:
David Abrahams wrote:
"Peter Dimov"
writes: David Abrahams wrote:
ADL might not be the best customization solution.
You keep saying that, but I keep disagreeing. ADL is the best customization solution. Not flawless, just better than any of the alternatives.
I guess I haven't seen enough be definitively convinced one way or the other. I have heard stories from people who switch to dispatching via specialization and report how much better things get. Furthermore, Daveed Vandevoorde has convinced me that it is far easier to reason about. The rules for matching partial specializations are trivial compared to the mess you have to consider when there is overloading. The inconvenience of specialization is ugly, but it seems like a one-time cost that may be justified for what it buys us.
That's the thing. It doesn't actually buy us anything. It only claims to avoid potential problems.
I would disagree with that - it buys quite a lot, although for simple uses the extra syntax might not be worth it.
* Uglier syntax for defining a specialization.
IME, this is the biggest cost. I would include also the (one-off) cost of providing a forwarding function to get a sane syntax for the outside world. That is OK if you have a closed set of functions because the forwarding function can be defined by the library, but if the library is merely providing a framework for user-supplied algorithms it becomes a bit messy.
* Coupling; you need to include a primary template.
Ok, but what does that primary template do? Surely nothing, or some very conservative default.
* Does not allow a base-specific version to be picked up automatically for derived classes.
But you can use a partial specialization heirachy instead. Something like
template <typename T>
struct forward_iterator {};
template <typename T>
struct bidirectional_iterator {};
// ...
typedef forward_iterator<void> forward_iterator_t;
typedef forward_iterator
* Does not allow non-exact matches.
You could use enable_if
* If four libraries need the same operation, you need to specialize four primary templates.
Compare to four libraries using an ADL lookup on the same function name, but requiring different semantics?
In practice people tend to respect de-facto standards; a + b is an addition, and swap(a, b) swaps a and b. The main fight is over who gets to keep the primary template. But this is not really a problem with ADL customization points, because in their purest form, there is no primary template. The primary template is usually a compatibility workaround for types that do not support the ADL interface yet.
Sure, for de-facto standard operations, ADL works fine. Cheers, Ian