begin (cout) or boost::copy to cout
== The Problem == Boost.Range defines boost:: begin to give you the iterator to every possible container — except ostream. == Solution 1 == === Implementation === I have the following function for you to add to Boost.Range: template < class P_I, class P_C, class P_T > std:: ostream_iterator < typename boost:: iterator_value < P_I >:: type, P_C, P_T > begin (std:: basic_ostream < P_C, P_T > &p_s, P_I const &, P_C const p_p [] = NULL) { return std:: ostream_iterator < typename boost:: iterator_value < P_I >:: type, P_C, P_T > (p_s, p_p); } === Application === to be used in the following way: void foo (std:: vector < int > const &v) { boost:: copy (v, boost:: begin (std:: cout, boost:: begin (v), " "); } This function eliminats the need of passing explicit template parameters to std:: ostream_iterator, which makes the code fragile and hard to read. == Solution 2 == === Motivation === Since an output stream iterator is not useful except for copying to an output stream, a further simplification is also possible: === Implementation === template < class P_R, class P_C, class P_T > std:: basic_ostream < P_C, P_T > © (P_R const &p_r, std:: basic_ostream < P_C, P_T > &p_s, P_C const p_p [] = NULL) { copy (p_r, std:: ostream_iterator < typename boost:: range_value < P_R >:: type, P_C, P_T > (p_s, p_p)); return p_s; } === Application === and it enables the following invocation: void foo (std:: vector < int > const &v) { boost:: copy (v, std:: cout, " "); } Please consider. Chris
AMDG On 09/13/2011 02:35 PM, Krzysztof Żelechowski wrote:
== The Problem ==
Boost.Range defines boost:: begin to give you the iterator to every possible container — except ostream.
Why is this a problem? An ostream is not a container. Neither of your proposed solutions make ostream a valid range, so overloading boost::begin is just confusing. I don't see what the problem with just using std::ostream_iterator directly is. In Christ, Steven Watanabe
This function eliminats the need of passing explicit template parameters to std:: ostream_iterator, which makes the code fragile and hard to read.
I agree that having to pass a template parameter to std::ostream_iterator is annoying. However, overloading boost::begin for std::ostream is not a good solution, because, as Steven pointed out, ostream is not a range. (And certainly, overloading boost:copy for something as specific as std::ostream is not a good solution - it goes directly against the spirit of generic programming, which is to express algorithms in terms of a generic interface (iterators), and have data structures adapt to that interface). A better solution is to write a polymorphic version of ostream_iterator; that is, a version that's not a template, but which has a templated operator=, so that you can output any type using the iterator. With such a modified ostream_iterator, you can write: boost:copy(some_range, my_ostream_iterator(cout, " ")); which is very close to what you are aiming for. Regards, Nate
AMDG On 09/13/2011 05:41 PM, Nathan Ridge wrote:
This function eliminats the need of passing explicit template parameters to std:: ostream_iterator, which makes the code fragile and hard to read.
I agree that having to pass a template parameter to std::ostream_iterator is annoying.
However, overloading boost::begin for std::ostream is not a good solution, because, as Steven pointed out, ostream is not a range. (And certainly, overloading boost:copy for something as specific as std::ostream is not a good solution - it goes directly against the spirit of generic programming, which is to express algorithms in terms of a generic interface (iterators), and have data structures adapt to that interface).
A better solution is to write a polymorphic version of ostream_iterator; that is, a version that's not a template, but which has a templated operator=, so that you can output any type using the iterator.
I suspect that it would be difficult to make a valid STL iterator like that. How would you define std::iterator_traits for it?
With such a modified ostream_iterator, you can write:
boost:copy(some_range, my_ostream_iterator(cout, " "));
which is very close to what you are aiming for.
In Christ, Steven Watanabe
This function eliminats the need of passing explicit template parameters to std:: ostream_iterator, which makes the code fragile and hard to read.
I agree that having to pass a template parameter to std::ostream_iterator is annoying.
...
A better solution is to write a polymorphic version of ostream_iterator; that is, a version that's not a template, but which has a templated operator=, so that you can output any type using the iterator.
I suspect that it would be difficult to make a valid STL iterator like that. How would you define std::iterator_traits for it?
ostream_iterator already has "void" as its value_type, difference_type, pointer, and reference (and so do other standard output iterators like insert_iterator)... so there would be no difference between the standard version and the modified version in that regard. Regards, Nate
participants (3)
-
Krzysztof Żelechowski
-
Nathan Ridge
-
Steven Watanabe