[range?] Re: Partial specialization matching

The following message is a courtesy copy of an article that has been posted to comp.lang.c++.moderated as well. [I'm Cc'ing this to Boost because IIRC some people were struggling with a similar issue recently. Of course it may not apply ;-)] "Nicolas" <nicolas.tisserand@gmail.com> writes:
Ben Hutchings wrote:
[snip]
I believe it was considered unreasonable to require implementers to do that kind of analysis, given that it could involve checking for specialisations across the whole program.
Got that. Thanks :)
In the code I posted, I was trying to specialize a class template (IteratorTraits) according to the relationship between an Iterator and its Container. For instance, I wanted to be able to produce a specialization of IteratorTraits for what std::vector<T, Alloc> advertises as being its iterator type.
It's fundamentally impossible [unless the core language was to make exceptions based on special knowledge about certain standard library components]. Forget everything you know about vectors, and now consider: template <class Iterator> struct IteratorTraits; template <class T> struct vector { typedef char* iterator; }; // This would be the syntax, if it were legal. template <class T> struct iterator_traits<vector<T>::iterator> { // What is T? }; It's illegal because there's no way for the compiler to deduce T.
Is there a way to do that without having to examine a given STL implementation and find out what the exact type of std::vector<T, Alloc>::iterator is?
Technically, no. *If* you're willing to assume that std::vector<T,A>::iterator is the same type for any A (which is not quite correct in any real implementation because of vector<bool>), you could do this: template <class Iterator, class Enable = void> struct IteratorTraits; template <class Iterator> struct IteratorTraits< Iterator , boost::enable_if< boost::is_same< Iterator , typename std::vector< typename std::iterator_traits<Iterator>::value_type >::iterator > >::type
{ // whatever you want here. }; This specialization of IteratorTraits applies iff the iterator type of a vector of the argument's value_type is the same as the argument. I'm sure you can figure out how to deal with the vector<bool> anomaly. See http://www.boost.org/libs/utility/enable_if.html for information about how enable_if works with class template specializations. HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
*If* you're willing to assume that std::vector<T,A>::iterator is the same type for any A (which is not quite correct in any real implementation because of vector<bool>), you could do this:
I'm pretty sure it would be possible to implement vector<bool>'s so that it could be the same for any A since it's just pointing to raw memory. The iterator only has to different for different allocators when the data it's need to access is dependant on the allocator (such as a node which contains an 'A::pointer'). Or am I missing something? Of course, you can't assume that. Daniel

Daniel James <daniel@calamity.org.uk> writes:
David Abrahams wrote:
*If* you're willing to assume that std::vector<T,A>::iterator is the same type for any A (which is not quite correct in any real implementation because of vector<bool>), you could do this:
I'm pretty sure it would be possible to implement vector<bool>'s so that it could be the same for any A since it's just pointing to raw memory. The iterator only has to different for different allocators when the data it's need to access is dependant on the allocator (such as a node which contains an 'A::pointer'). Or am I missing something?
You're missing something. There's a specialization of vector<bool, allocator<bool> > in the standard whose iterators iterate over bits and use a proxy reference and therefore are not even conforming forward iterators. vector<bool,A> for A != allocator<bool> is still required to have conforming random-access iterators. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
There's a specialization of vector<bool, allocator<bool> > in the standard whose iterators iterate over bits and use a proxy reference and therefore are not even conforming forward iterators. vector<bool,A> for A != allocator<bool> is still required to have conforming random-access iterators.
But I don't think that means that you need different iterator types for different allocators. The data is still just raw data, an array of (say) chars instead of bools. Daniel

Daniel James <daniel@calamity.org.uk> writes:
David Abrahams wrote:
There's a specialization of vector<bool, allocator<bool> > in the standard whose iterators iterate over bits and use a proxy reference and therefore are not even conforming forward iterators. vector<bool,A> for A != allocator<bool> is still required to have conforming random-access iterators.
But I don't think that means that you need different iterator types for different allocators. The data is still just raw data, an array of (say) chars instead of bools.
std::iterator_traits<std::vector<bool>::iterator>::reference is different from std::iterator_traits<std::vector<bool,A>::iterator>::reference for all A != std::allocator<bool> Therefore std::vector<bool>::iterator is different from std::vector<bool,A>::iterator for all A != std::allocator<bool> QED -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote
template <class Iterator, class Enable = void> struct IteratorTraits;
template <class Iterator> struct IteratorTraits< Iterator , boost::enable_if< boost::is_same< Iterator , typename std::vector< typename std::iterator_traits<Iterator>::value_type >::iterator > >::type
{ // whatever you want here. };
If the following proposal was accepted it might even be possible to do without the extra parameter :-) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1696.html regards Andy Little
participants (3)
-
Andy Little
-
Daniel James
-
David Abrahams