
Hello, I found that the input/output and comparison functions for iterator_range are inside the header boost/range/iterator_range.hpp. Actually, this causes problems, as I can't provide custom printing and custom comparison: I have my own container printing engine and it worked perfectly well with all standard containers, but failed to compile with iterator_range due to operator<< ambiguity. (Of course, I can just disable instantiation of my printing stuff for iterator_range, but this is definitely not what I want to have.) And, I have no such problems with, say, boost::tuple, as it has separate headers for printing and comparison: #include "boost/tuple/tuple_comparison.hpp" #include "boost/tuple/tuple_io.hpp" There are also other boost libraries that provide a separate "XXX_io.hpp" header. So my proposal is: 1. Move operator<< to a separate header "boost/range/iterator_range_io.hpp" 2. Move comparison operators to a separate header "boost/range/iterator_range_comparison.hpp" This will also serve for boost unification, which is the Right Thing that greatly simplifies usage of any library collection. However, two problems arise here: 1. Backward compatibility. Current programs expect that everything is automatically included. I see two solutions: - Include "boost/range/iterator_range_io.hpp" and "boost/range/iterator_range_comparison.hpp" into "boost/range/iterator_range.hpp" under a define like BOOST_RANGE_1_34_COMPATIBILITY_MODE. This will give the same layout as we have in Boost.Tuple, but I don't want to introduce extra macros if they can be easily avioded. - Make one extra header "boost/range/iterator_range_core.hpp", and have "boost/range/iterator_range.hpp" just including everything. This will the hierarchical layout similar to other libraries like Boost.Spirit. In this case, maybe it worth moving all three new headers to a subdirectory. 2. Again, backward compatibility, but from another point of view. Boost.Range has the unspecified_bool_type() conversion operator. I personally don't see a strong need in it, as it's just a negation of empty(). Also, no standard containers (which are ranges) offer this kind of conversion. So I don't expect wide use of it, and maybe it's worth removing it from the class at all and leave empty() only. Anyway, for now it's here, so if you move operator<< away, iterator_range will continue to be printed, but now, due to this conversion, it will be just "0" or "1", depending on the range emptiness. This is the problem not only for Boost.Range, but also for other types that offer this kind of conversion and separate printing, for example, consider this simple program with Boost.Optional: #include <boost/optional/optional.hpp> boost::optional<char> o('o'); #include <iostream> void without_io() { std::cout << "without_io: " << o << '\n'; } #include <boost/optional/optional_io.hpp> void with_io() { std::cout << "with_io: " << o << '\n'; } int main() { without_io(); with_io(); } So, whether we change Boost.Range header leayout or not, this unspecified_bool_type() problem should be solved anyway, for several boost classes. I discussed this with Alex Nasonov, and he proposed a patch for boost::optional: https://svn.boost.org/trac/boost/ticket/2103 But this is not the only use of unspecified_bool_type, so most probably we will need a common solution. Thanks, Maxim P.S. Please write personal e-mails to gmail.com.