Opened 15 years ago
Last modified 10 years ago
#1315 new Feature Requests
iterator_adaptor does not work with incomplete Value types
Reported by: | Joaquín M López Muñoz | Owned by: | jeffrey.hellrung |
---|---|---|---|
Milestone: | To Be Determined | Component: | iterator |
Version: | Boost Development Trunk | Severity: | Problem |
Keywords: | Cc: | duncanphilipnorman@… |
Description
boost::iterator_adaptor doesn't work when the associated Value type is incomplete, at least in MSVC++ 8.0 (my hunch is that the problem is general). The following
#include <boost/iterator/iterator_adaptor.hpp> template<typename T> struct my_iterator: boost::iterator_adaptor<my_iterator<T>,T*> { }; struct foo { my_iterator<foo> it; }; int main(){}
results in:
...\boost\type_traits\is_pod.hpp(34) : error C2139: 'foo' : an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_pod' ...\sandbox.cpp(10) : see declaration of 'foo' ...\type_traits\is_pod.hpp(128) : see reference to class template instantiation 'boost::detail::is_pod_impl<T>' being compiled [...] ...\boost\iterator\iterator_facade.hpp(652) : see reference to class templateinstantiation 'boost::detail::operator_brackets_result<Iterator,Value,Reference>' being compiled with [ Iterator=my_iterator<foo>, Value=foo, Reference=foo & ] [...]
Although this is probably not a bug strictly speaking, it would be fine if iterator_adaptor could be made to work with incomplete Value types, just as the canonical model for iterators, Value*, does.
Change History (10)
comment:1 by , 14 years ago
comment:2 by , 14 years ago
As far as I have understood, when iterator_facade<Derived,Value,Category,...>
is instanciated, the type Value
is required to be complete because of the following member function prototype:
typename detail::operator_brackets_result<Derived,Value,reference>::type operator[](difference_type n) const
which triggers the instanciation of use_operator_brackets_proxy<Value,Reference>
(in the same file), which triggers the instanciation of is_POD<Value>
, which requires a complete type.
follow-up: 6 comment:3 by , 14 years ago
Status: | new → assigned |
---|
I think your analysis is correct, but my question to you is: why should this be considered a bug?
I can only think of one way around it, and that's to templatize operator[]
.
follow-up: 5 comment:4 by , 14 years ago
I think your analysis is correct, but my question to you is: why should this be considered a bug?
Because T*, which is the type upon which iterators are modelled, can be instantiated on incomplete types. I've checked section 24.1 of the standard and this requirement does not seem to be explicitly stated, but IMHO it's a nice feature to have, given that 24.1.2 recognized iterators as an abstraction of pointers. FWIW, I first encountered the problem in the context of a real situation.
I can only think of one way around it, and that's to templatize operator[]
Correct. Please see
http://lists.boost.org/Archives/boost/2007/10/128738.php
where I propose a possible implementation of the workaround.
comment:5 by , 14 years ago
Owner: | changed from | to
---|---|
Status: | assigned → new |
Replying to joaquin:
I think your analysis is correct, but my question to you is: why should this be considered a bug?
Because T*, which is the type upon which iterators are modelled, can be instantiated on incomplete types.
Technically, T* can't be instantiated, since it isn't a template.
I've checked section 24.1 of the standard and this requirement does not seem to be explicitly stated, but IMHO it's a nice feature to have, given that 24.1.2 recognized iterators as an abstraction of pointers. FWIW, I first encountered the problem in the context of a real situation.
Exactly, a nice feature to have. I think this is a feature request... which is why you've labelled it as such. OK, objection withdrawn ;-)
I can only think of one way around it, and that's to templatize operator[]
Correct. Please see
http://lists.boost.org/Archives/boost/2007/10/128738.php
where I propose a possible implementation of the workaround.
Thomas: I guess since operator[] has to be a member function, we wouldn't gain anything by enable-if'ing it?
follow-up: 7 comment:6 by , 14 years ago
Replying to dave:
I think your analysis is correct, but my question to you is: why should this be considered a bug?
It is more a feature request than a bug. In a software of ours, CGAL, we would like to use the features of iterator_facade
, in a scenario alike the one I posted in comment 1. It currently works with GNU/g++ (versions 4.1.2 and 4.3.0 at least), even if I do not know why, but not with MSVC++ 8.
follow-up: 8 comment:7 by , 12 years ago
Cc: | added |
---|
Replying to Laurent Rineau <Laurent.Rineau__boost@…>:
Replying to dave:
I think your analysis is correct, but my question to you is: why should this be considered a bug?
It is more a feature request than a bug. In a software of ours, CGAL, we would like to use the features of
iterator_facade
, in a scenario alike the one I posted in comment 1. It currently works with GNU/g++ (versions 4.1.2 and 4.3.0 at least), even if I do not know why, but not with MSVC++ 8.
This feature worked in GCC only because of a bug prior to v4.4 (e.g., you could use abstract types in v4.3.4). However, this bug -- to do with the intrinsics __is_abstract
and __is_pod
-- was fixed:
GCC v4.4.3 now gives the same as MSVC. In particular, iterator_facade<>
cannot be used to wrap pointers to abstract types any longer. With a large codebase that accidentally relied on this misbehaviour, we cannot upgrade past GCC v4.3 without this feature.
Does anyone know if the workaround above causes any problems?
comment:8 by , 12 years ago
Replying to Duncan Exon Smith <duncanphilipnorman@…>:
This feature worked in GCC only because of a bug prior to v4.4 (e.g., you could use abstract types in v4.3.4). However, this bug -- to do with the intrinsics
__is_abstract
and__is_pod
-- was fixed:GCC v4.4.3 now gives the same as MSVC. In particular,
iterator_facade<>
cannot be used to wrap pointers to abstract types any longer. With a large codebase that accidentally relied on this misbehaviour, we cannot upgrade past GCC v4.3 without this feature.
BTW, in case anyone else is searching for it, there's a similar problem with boost::iterator_range<>
, from Boost.RangeEx, since it uses is_abstract<>
. Incomplete types cannot be used there, either.
comment:9 by , 10 years ago
Owner: | changed from | to
---|
comment:10 by , 10 years ago
Since I saw this changed owners, I should maybe give some feedback. We've been using something similar to the workaround above for a couple of years, and it has worked well.
- There are a few places in the file that need to be templated on
Difference
. - We've applied similar patches to parts of Boost.Range.
E.g., our version of the relevant code from the linked patch is:
template <typename DummyDifference> typename boost::lazy_enable_if < boost::is_convertible<DummyDifference, difference_type> , typename boost::detail::operator_brackets_result<Derived,Value,reference,DummyDifference>::type >::type operator[](DummyDifference n_) const { difference_type n(n_);
I encounter this bug with a code example a bit more tricky:
g++-4.1.2 and g++-4.3.0 do compile the code above, with boost-1.34.1 or with boost trunk (revision 44750), but MSVC++ 8.0 does not (same error diagnostic as the bug submitter):