|
Boost Users : |
From: David Abrahams (dave_at_[hidden])
Date: 2005-03-05 12:46:08
"Peter Dimov" <pdimov_at_[hidden]> writes:
> David Abrahams wrote:
>> "Peter Dimov" <pdimov_at_[hidden]> writes:
>>
>>> Ian McCulloch wrote:
>>>> Peter Dimov wrote:
>>>>
>>>>> Right. And if they did not collide, nothing would become a de-facto
>>>>> standard, because people could keep using their own versions. There
>>>>> would be no pressure to resolve these collisions.
>>>>
>>>> So even on boost, such collisions occur - what about libraries that
>>>> are developed completely independently? Which politburo is to
>>>> decide how each name is supposed to be used? How is it to be
>>>> enforced?
>>>
>>> It is unenforceable, of course. But this doesn't mean that it can't
>>> happen. Library authors are, in general, reasonable people; they do
>>> cooperate and do respond to issues.
>>
>> I don't know about that. The various placeholders in Boost still have
>> usability problems when #included together. And the bind placeholders
>> are still causing ODR violations.
>
> The placeholders do have the same meaning; they are an example of a de-facto
> standard.
> The conflicts that exist are (a) resolvable, (b) caused by factors
> that do not apply to our discussion.
Not exactly. I'm thinking of MPL and bind actually. They don't have
the same meaning, only a similar one, and they can't be unified. It's
the very "standard-ness" that prompted MPL to use the same names in a
very similar -- but not identical -- way.
> And for the record, Lambda's placeholders cause exactly the same ODR
> violations, although I'm not sure whether "cause" is the proper term.
You're right, "lead to" would be more accurate. I hope you understand
the following:
1. I'm arguing about this because I want to end up convinced of
something, and soon -- I'll need to choose customization techniques
imminently -- so thank you for engaging me on this.
2. I only brought up the ODR thing as a piece of evidence that
problems don't neccessarily get resolved quickly
>> It's all very well that library writers may adjust eventually, but
>> users can't always upgrade, or they can't always upgrade quickly.
>> There ought to be a mechanism for staying out of one another's way.
>
> Such a mechanism does exist.
Yeah, but it's cumbersome, and has a few other problems some of which
you've mentioned. With that sentence I was arguing that we ought to
have a mechanism that works more smoothly, and suggesting that -- with
the right language changes -- avoidance of the problems with the
current mechanism does not _have_ to imply the use of ADL.
> I maintain that not using this mechanism is better in the long term.
Why?
>>> This isn't really specific to ADL customization points. Consider, for
>>> example, container requirements, where a.begin() must return
>>> A::iterator or A::const_iterator. What happens if another library
>>> has its own requirements table that specifies different semantics
>>> for a.begin()? Can I make my container conform to these requirements
>>> as well? Of course not.
>>
>> That's why generic library writers have developed a guideline to write
>> concept requirements that don't depend on member functions.
>
> Maybe they did. My point is that I never see anti-v.begin()
> campaigns;
I do. Why do you think Boost.Range is using free functions? Not
putting member functions in concept requirements is a well-known
generic programming guideline. For years even Scott Meyers has been
saying that "interfaces should be extended with free functions," which
isn't viewed through the generic customization-point lens, but means
the same thing.
> it's ADL that gets all the flack.
I think that's because ADL has too many problems besides the one we're
discussing right here (intrusive name reservation). Also because once
we understand that member function requirements are a bad idea, we're
forced to face those other problems and (I at least) anguish over
whether to live with them or take the leap into using specialization.
And because GCC's liberal interpretation of ADL screws everyone
eventually ;-)
>>>> And wern't namespaces supposed to solve these issues anyway?
>>>
>>> The central question is: can we, the C++ community, decide on a
>>> common vocabulary for the primitive operations a type supports? If
>>> we can, there is no problem.
>>
>> I disagree most strongly.
>>
>> One problem is that not all operations are going to be considered
>> "primitive." More importantly, there should be a way to develop
>> software with confidence that it has a future and scales well, without
>> having to worry that all customizable names are "pending the
>> community's verdict on common meaning."
>
> See above; there is such a way
Sorry, I can't connect the dots. What way?
> and the debate is whether not having to
> worry is a good thing. Customization points are very important and need to
> be treated with caution.
What kind of caution, if they are associated with a namespace, and
why? We could use std::iterator_traits as an example.
> Once they become de-facto standards, the library no
> longer owns them, even if they are in the library's own namespace.
Even if I understood what you meant by "the library no longer owns
them, even if they are in the library's own namespace," what are the
implications of that? Is std::iterator_traits an example of a
de-facto standard customization point in a namespace?
There are clearly some (just a very few, IMO) customization points
like swap that are really intrinsic. They have to do with the
semantics of what Stepanov and friends are calling "value types." It
seems to me as though the rest are associated with a particular
domain, and it's appropriate to name that domain.
>>>>>> Just consider the widespread use of numeric types in all kinds of
>>>>>> domain-specific applications. Is every library going to pick the
>>>>>> same meaning for
>>>>>>
>>>>>> zero(x)
>>>>>>
>>>>>> ??
>>>>>
>>>>> Yes, I hope so. I also hope that they would pick the same meaning
>>>>> for x+y.
>>>>
>>>> Ok, quick (but serious) question: What are the semantics of zero(x)
>>>> ?
>>>
>>> I don't know; this is Dave's example. Whatever the community
>>> decides, as long as it's consistent. The user should learn what it
>>> means _once_.
>>
>> It could take many years for a name like that to settle down,
>> especially if two major libraries with strong user base and
>> backward-compatibility considerations pick competing definitions.
>
> OK; so what alternatives do we have?
>
> 1. lib1::numeric_traits<X>::zero( x ); // somewhat unwieldy
> 2. lib1::zero( x ); // syntactic sugar for the above
> 3. lib1_zero( x );
>
> What, exactly, are the advantages of #2 over #3?
#3 invokes ADL.
> That you can bring lib1::zero into scope with a using declaration
> and call it unqualified?
Of course not! Getting the ability to make unqualified calls is not
the goal here. Rather, the ability to make _qualified_ calls is
valuable: it's more predictable, and it says what it means, and it
avoids potential name choice collision problems, and...
> Current language assumed. In this discussion I do not consider your
> extension proposal; it will take even more years to settle down.
Fair enough; I need answers urgently for the current language myself.
You can ignore my one allusion to extensions in this thread; the rest
of what I've written here deals with the current language.
Thanks again,
-- Dave Abrahams Boost Consulting www.boost-consulting.com
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net