Opened 10 years ago
Closed 9 years ago
#7376 closed Bugs (fixed)
join_iterator.hpp compiler warning
Reported by: | Owned by: | Neil Groves | |
---|---|---|---|
Milestone: | To Be Determined | Component: | range |
Version: | Boost 1.51.0 | Severity: | Problem |
Keywords: | Cc: |
Description
getting compiler warning in boost/range/detail/join_iterator.hpp:74
53 template<typename Iterator1 54 , typename Iterator2 55 , typename Reference 56 > 57 class join_iterator_union 58 { 59 public: 60 typedef Iterator1 iterator1_t; 61 typedef Iterator2 iterator2_t; 62 63 join_iterator_union() {} 64 join_iterator_union(unsigned int /*selected*/, const iterator1_t& it1, const iterator2_t& it2) : m_it1(it1), m_it2(it2) {} 65 66 iterator1_t& it1() { return m_it1; } 67 const iterator1_t& it1() const { return m_it1; } 68 69 iterator2_t& it2() { return m_it2; } 70 const iterator2_t& it2() const { return m_it2; } 71 72 Reference dereference(unsigned int selected) const 73 { 74 return selected ? *m_it2 : *m_it1; 75 } 76 77 bool equal(const join_iterator_union& other, unsigned int selected) const 78 { 79 return selected 80 ? m_it2 == other.m_it2 81 : m_it1 == other.m_it1; 82 } 83 84 private: 85 iterator1_t m_it1; 86 iterator2_t m_it2; 87 };
I am using it in a way when iterator1_t and iterator1_t are different types. Furthermore, underlying types (*m_it1 and *m_it2) are different, but both are convertible to Reference, but not to each other.
In other words expression *m_it2 cannot be converted to type iterated by iterator1_t ( *m_it1 ). But can be safely converted to type Reference
please consider following patch:
@@ -68,7 +68,9 @@ Reference dereference(unsigned int selected) const { - return selected ? *m_it2 : *m_it1; + if (selected) + return *m_it2; + return *m_it1; } bool equal(const join_iterator_union& other, unsigned int selected) const
Change History (7)
comment:1 by , 10 years ago
Component: | None → range |
---|---|
Owner: | set to |
comment:2 by , 9 years ago
follow-up: 4 comment:3 by , 9 years ago
here is a sample code that produces compiler error:
#include "boost/range/join.hpp" struct A {}; struct B: public A {} ; struct C: public A {}; int main() { B b[10]; C c[10]; typedef ::boost::range_detail::join_iterator< const C*, const B* , const A&, const A& > join_iterator; join_iterator it(::boost::make_iterator_range(c), ::boost::make_iterator_range(b), ::boost::range_detail::join_iterator_begin_tag()); *it; }
error:
boost/range/detail/join_iterator.hpp:74: error: no match for ternary 'operator?:' in '(selected != 0u) ? *(const B*)((const boost::range_detail::join_iterator_union<const C*, const B*, const A&>*)this)->boost::range_detail::join_iterator_union<const C*, const B*, const A&>::m_it2 : *(const C*)((const boost::range_detail::join_iterator_union<const C*, const B*, const A&>*)this)->boost::range_detail::join_iterator_union<const C*, const B*, const A&>::m_it1
with patch suggested earlier this sample compiles without errors.
comment:4 by , 9 years ago
Replying to anonymous:
here is a sample code that produces compiler error:
#include "boost/range/join.hpp" struct A {}; struct B: public A {} ; struct C: public A {}; int main() { B b[10]; C c[10]; typedef ::boost::range_detail::join_iterator< const C*, const B* , const A&, const A& > join_iterator; join_iterator it(::boost::make_iterator_range(c), ::boost::make_iterator_range(b), ::boost::range_detail::join_iterator_begin_tag()); *it; }error:
boost/range/detail/join_iterator.hpp:74: error: no match for ternary 'operator?:' in '(selected != 0u) ? *(const B*)((const boost::range_detail::join_iterator_union<const C*, const B*, const A&>*)this)->boost::range_detail::join_iterator_union<const C*, const B*, const A&>::m_it2 : *(const C*)((const boost::range_detail::join_iterator_union<const C*, const B*, const A&>*)this)->boost::range_detail::join_iterator_union<const C*, const B*, const A&>::m_it1
with patch suggested earlier this sample compiles without errors.
join_iterator is not part of the public interface of Boost.Range, it's just an implementation detail of boost::range::join().
boost::range::join() currently requires that the value type of the second range be convertible to the value type of the first range. Perhaps this requirement could be relaxed, to allow cases where the two value types are convertible to a common type but not to each other, but then we need to either:
- get join_iterator to figure out what that common type is (which is possible in some cases like this one, but not in the general case); or
- provide a public interface for the user to specify this common type (right now you are specifying it by instantiating join_iterator with a custom Reference template parameter, which is not public interface)
(or both).
Your patch will probably be part of either solution, but I am inclined to wait until we have a complete solution before applying it.
comment:5 by , 9 years ago
Status: | new → assigned |
---|
I think that specifying the Reference type of the join_iterator is already a way to manage the "common type" problem. I don't think that there is a general solution to the "common type" problem when we consider the potential interaction with user-defined types. It is possible that the desired return type isn't a reference in any of the input types. Manual specification is already possible, is simple and works.
I'm going to apply the small change as requested.
comment:6 by , 9 years ago
Additionally aschoedl provided some extra code to do better automatic deduction of common-types.
comment:7 by , 9 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Could you please give an example of Iterator1 and Iterator2 types for which this problem arises?