Opened 11 years ago
Last modified 11 years ago
#5963 new Patches
Patch [Fixes #5961]: Disallow comparisons of differing iterator types in ptr_container
Reported by: | Owned by: | Thorsten Ottosen | |
---|---|---|---|
Milestone: | To Be Determined | Component: | ptr_container |
Version: | Boost 1.47.0 | Severity: | Problem |
Keywords: | iterator, type, compare | Cc: |
Description
Patch removes support for comparing differing iterator types from ptr_container's void_ptr_iterator. The comparators in question are == != < <= > >=.
Changes are:
- Add container type template parameter to void_ptr_iterator. This is what ensures compared iterators of differing types are still for the same referenced container type.
- Add self type as template argument to base class for containers ptr_array, ptr_circular_buffer, ptr_deque, ptr_list, ptr_set, ptr_multiset, ptr_unordered_set, ptr_unordered_multiset, and ptr_vector
- Pass container type template parameter from sequence_config and set_config to iterator typedefs, from ptr_sequence_adapter to reversible_ptr_container, and from ptr_set_adapter and ptr_multiset_adapter through ptr_set_adapter_base to associative_ptr_container
Attachments (3)
Change History (14)
by , 11 years ago
Attachment: | ptr_container.vp_iterator.comparators.patch added |
---|
by , 11 years ago
Attachment: | ptr_container.vp_iterator.comparators.2.patch added |
---|
Patch to ptr_container to fix #5961
comment:2 by , 11 years ago
Hi,
Thanks for the patch. However, I do not think its the right way to do it. I think it generates too many iterator types, and I think there must be a much simpler fix.
I'm thinking out of the box, partially because I cannot remember why the code takes parameters U and T. Maybe it is because that U and T are always either X or const X.
That is, it may be possible to fix the problem by using enable_if<> that requires that is_same< remove_const<U>, remove_const<T> >::value is true.
-Thorsten
comment:3 by , 11 years ago
Ah yes, didn't think of the number of resulting types that would be generated..
Using enable_if<> etc. as you suggest looks good. Since we can't use enable_if<> either as a dummy parameter (since these are binary operators) or as the return value (since we're using it) I'd suggest we create a helper traits that defines non-operator equivalents of these operations. Would you agree that's the way to go?
(NB: we technically /could/ put enable_if<> in the return, but that would make for a horrible public interface.)
comment:4 by , 11 years ago
Hm.
Maybe it would be sufficient to put a static assert + comment in the body of the involved functions.
-Thorsten
comment:5 by , 11 years ago
Yes that would be simpler..
How about the following?
// Helper struct that determines compatibility template<typename T, typename U> struct_is_compatible { static const bool value = typename boost::is_same< typename boost::remove_const<T>::type, typename boost::remove_const<U>::type >::value; }; // And add the assertion to each operator like this: template< class VoidIterT, class T, class VoidIterU, class U > inline bool operator==( const void_ptr_iterator<VoidIterT,T>& l, const void_ptr_iterator<VoidIterU,U>& r ) { BOOST_STATIC_ASSERT((is_compatible<T, U>::value)); // ... }
where should the helper struct go? I'm guessing directly in the boost namespace isn't ideal..
comment:6 by , 11 years ago
Thorsten's enable_if solution has the advantage that instantiation errors will be reported in user's code, whereas the static assert will generate errors in Boost headers, which is not ideal.
comment:7 by , 11 years ago
@anonymous author of comment 6 - indeed, I agree it's not great having the error appear in the header, but due to reasons outlined in comment 3, it's not possible to push this error back to the user code (as far as I know - suggestions welcomed.)
comment:8 by , 11 years ago
I guess the usual way to handle errors in Boost code is to make a clear comment saying why you got this error. E.g. Boost.Serialization and Boost.Range does this.
After all, the important this is that you get an error.
comment:9 by , 11 years ago
Indeed - since getting the error is after all the point of this, I'll make it use BOOST_STATIC_ASSERT_MSG() to be helpful.
comment:10 by , 11 years ago
Actually I was talking rubbish earlier, we /can/ use enable_if in the operator because it can wrap any type you pass as the second template param. I've wrapped all the return types in question with an enable_if using the new struct ptr_container_detail::is_compatible.
My own tests and those in /libs/ptr_container/test all check out fine, error messages are helpful and appear for the offending line of user code.
by , 11 years ago
Attachment: | ptr_container.vp_iterator.comparators.3.patch added |
---|
Revised patch obsoletes earlier patches
Patch to ptr_container to fix #5961