Niels Dekker contributed an interesting bug report regarding the use of swap(). swap() is particularly interesting, because it is essentially the only algorithm in the C++ Standard Library that is really meant to be customized. The example is quite small:
template <std::Swappable T>
void SwapTheSwappable(T& lhs, T& rhs) {
using std::swap;
swap(lhs, rhs); // ConceptGCC error: no matching function for call...
}
This function (SwapTheSwappable) ConceptGCC rejects the call to swap() because the type ‘T’ does not meet the Assignable and CopyConstructible requirements. To see why, we first need to look at std::swap:
template <typename T>
where CopyConstructible<T> && Assignable<T>
void swap(T& x, T& y) {
T tmp(x);
x = y;
y = tmp;
}
The Swappable concept then looks like this:
auto concept Swappable<typename > {
void swap(T&, T&)
}
For any CopyConstructible and Assignable type, the Swappable requirements are automatically met by the std::swap template. Users can provide their own swap function in an associated namespace or write a concept map to provide a different implementation of swap.
So why does SwapTheSwappable fail? Name lookup for the call swap(lhs, rhs) finds the std::swap declared by the using declaration (“using std::swap”), and stops there. Since this function template requires Assignable and CopyConstructible, which aren’t requirements for SwapThisSwappable, the call fails. ConceptGCC never even looks at the swap() function in the Swappable concept, which would work.
If one removes the “using std::swap” line, ConceptGCC finds swap() in Swappable, and everything works. The problem is that “using std::swap” is the way that C++ programmers have been taught to write templates that use swap(), and it’s unfortunate that the only right way to handle swap in pre-concept code does not work with concepts.
This is a good reason to revisit the “lexical scoping” rule for name lookup into concepts. For instance, if having the using declaration meant only that std::swap would be overloaded with Swappable<T>::swap, the code would still work as intended.
January 6, 2007 at 10:53 pm |
Thanks Douglas, I very much appreciate the way you deal with my questions regarding std::Swappable.
Once the problem with “using std::swap” is fixed, it looks like the introduction of the std::Swappable concept would indeed resolve the issue that I submitted to the Library Working Group, http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#594
Keep up the good work!