
Doug Gregor wrote:
Ah, this is the issue at hand. Yes, we change when and how names are bound. There are still two phases to I'll use the lower_bound algorithm to illustrate how name resolution works:
template<InputIterator Iter> void advance(Iter& x, difference_type n); // #1 template<BidirectionalIterator Iter> void advance(Iter& x, difference_type n); // #2
template<ForwardIterator Iter> where LessThanComparable<value_type> Iter lower_bound(Iter first, Iter last, const value_type& value) { difference_type n = distance(first, last); Iter mid = first; advance(mid, n/2); // we're concerned with this call... }
template<RandomAccessIterator Iter> void advance(Iter& x, difference_type n); // #3
When we initially type-check lower_bound, we need to determine if there is an advance() that we can call. Both #1 and #2 have been seen, so we check them. Can we call #1? Sure, because every ForwardIterator is also an InputIterator. Can we call #2? Nope, our ForwardIterator is not guaranteed to be a BidirectionalIterator. So, we call #1 our "seed" function and use it for type-checking the template. Type-checking succeeds.
Question #1, what happens when there is no seed?
Now, let's consider what happens with this call to lower_bound:
vector<int> v; lower_bound(v.begin(), v.end(), 17);
When instantiating a template that uses concepts, we don't perform the normal second phase lookup with ADL. Instead, we do a more limited lookup designed to make sure that instantiation cannot fail [*]. So, when we instantiate the call to advance() in lower_bound(), we start with our "seed" function #1. We then look for any other functions named "lower_bound" in the same namespace as our seed that are specializations of the seed, and add those functions to our candidate set along with the seed.
Question #2, what happens in the swap() case? The seed (if there's one) is std::swap, but the actual call must go to the specialized swap in the type's namespace.