diff --git a/doc/boost_range.qbk b/doc/boost_range.qbk index 406d1a8..d509fb9 100644 --- a/doc/boost_range.qbk +++ b/doc/boost_range.qbk @@ -64,13 +64,13 @@ [def __irange__ [link range.reference.ranges.irange `irange`]] [def __istream_range__ [link range.reference.ranges.istream_range `istream_range`]] [def __combine__ [link range.reference.utilities.combine `combine`]] -[def __separated__ [link range.reference.utilities.separated `separated`]] [def __join__ [link range.reference.utilities.join `join`]] [def __range_adaptors__ [link range.reference.adaptors Range adaptors]] [def __range_adaptors_adjacent_filtered__ [link range.reference.adaptors.reference.adjacent_filtered adjacent_filtered]] [def __range_adaptors_copied__ [link range.reference.adaptors.reference.copied copied]] [def __range_adaptors_filtered__ [link range.reference.adaptors.reference.filtered filtered]] +[def __range_adaptors_formatted__ [link.range.reference.adaptors.reference.formatted formatted]] [def __range_adaptors_indexed__ [link range.reference.adaptors.reference.indexed indexed]] [def __range_adaptors_indirected__ [link range.reference.adaptors.reference.indirected indirected]] [def __range_adaptors_map_keys__ [link range.reference.adaptors.reference.map_keys map_keys]] diff --git a/doc/reference/adaptors/formatted.qbk b/doc/reference/adaptors/formatted.qbk new file mode 100644 index 0000000..9dd69c2 --- /dev/null +++ b/doc/reference/adaptors/formatted.qbk @@ -0,0 +1,51 @@ +[/ + Copyright 2014 Neil Groves + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +/] +[section:formatted formatted] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::formatted()`]] + [[Pipe] [`rng | boost::adaptors::formatted(sep)`]] + [[Pipe] [`rng | boost::adaptors::formatted(sep, prefix)`]] + [[Pipe] [`rng | boost::adaptors::formatted(sep, prefix, postfix)`]] + [[Function] [`boost::adaptors::format(rng)`]] + [[Function] [`boost::adaptors::format(rng, sep)`]] + [[Function] [`boost::adaptors::format(rng, sep, prefix)`]] + [[Function] [`boost::adaptors::format(rng, sep, prefix, postfix)`]] +] + +This adaptor produces a range that can be output streamed to a +`std::basic_ostream` to produce the output string formatted output. With the +default paramters given numbers 1 to 5 inclusively in a range the output when +streamed would be "{0,1,2,3,4,5}". The prefix, separator and postfix may be +passed as parameters. + +The general format of the output is thus: +... + +* [*Precondition:] + * `0 <= n`. + * `sep` has a type that is CopyConstructible and able to be streamed to `std::basic_ostream` + * `prefix` has a type that is CopyConstructible and able to be streamed to `std::basic_ostream` + * `postfix` has a type that is CopyConstructible and able to be streamed to `std::basic_ostream` +* [*Returns:] `boost::range::formatted_range` where +`Iter` is `typename boost::range_iterator::type`, `Sep` is the separator +type, `Prefix` is the prefix type and `Postfix` is the postfix type. +* [*Range Category:] __single_pass_range__ +* [*Returned Range Category:] The range category of `rng`. + +[section:formatted_example formatted example] +[import ../../../test/adaptor_test/formatted_example.cpp] +[separated_example] +[endsect] + +This would produce the output: +`` +{1,2,3,4,5} +`` +[endsect] + + diff --git a/doc/reference/utilities.qbk b/doc/reference/utilities.qbk index ae96e4b..24d11d7 100644 --- a/doc/reference/utilities.qbk +++ b/doc/reference/utilities.qbk @@ -10,7 +10,6 @@ Having an abstraction that encapsulates a pair of iterators is very useful. The * Class `iterator_range` * Class `sub_range` * Function `combine` -* Function `separated` * Function `join` The `iterator_range` class is templated on an __forward_traversal_iterator__ and should be used whenever fairly general code is needed. The `sub_range` class is templated on an __forward_range__ and it is less general, but a bit easier to use since its template argument is easier to specify. The biggest difference is, however, that a `sub_range` can propagate constness because it knows what a corresponding `const_iterator` is. @@ -405,55 +404,6 @@ For the mutable version: The expression `join(irange(0,5), irange(5,10))` would evaluate to a range representing an integer range `[0,10)` -[endsect] - -[section:separated Function separated] - -The separated function allows output streaming a range while writing a separator -between each element. - -[h4 Synopsis] - -`` -template -class output_stream_writer -{ - // ... unspecified -}; - -template -std::basic_ostream& operator<<( - std::basic_ostream& out, - const output_stream_writer& writer); - -template -boost::range::output_stream_writer< - typename boost::range_iterator::type, - Separator -> separated(const Range& rng, Separator separator); -`` - -[h4 Example] - -`` -#include -#include -#include - -int main(int, const char*[]) -{ - std::vector v; - for (int i = 0; i < 5; ++i) - v.push_back(v); - - std::cout << '{' << boost::range::separated(v, ',') << '}' << std::endl; - - return 0; -} -`` - -Produces the output: `{0,1,2,3,4}` - [endsect] [endsect] diff --git a/include/boost/range/adaptor/formatted.hpp b/include/boost/range/adaptor/formatted.hpp new file mode 100644 index 0000000..12ea5e4 --- /dev/null +++ b/include/boost/range/adaptor/formatted.hpp @@ -0,0 +1,224 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ADAPTOR_FORMATTED_HPP_INCLUDED +#define BOOST_RANGE_ADAPTOR_FORMATTED_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + +template +struct formatted_holder +{ + typedef typename boost::mpl::if_< + boost::is_array, + const typename boost::remove_extent::type*, + Sep + >::type separator_t; + + typedef typename boost::mpl::if_< + boost::is_array, + const typename boost::remove_extent::type*, + Prefix + >::type prefix_t; + + typedef typename boost::mpl::if_< + boost::is_array, + const typename boost::remove_extent::type*, + Postfix + >::type postfix_t; + + formatted_holder( + const separator_t& sep, + const prefix_t& prefix, + const postfix_t& postfix) + : m_sep(sep) + , m_prefix(prefix) + , m_postfix(postfix) + { + } + + separator_t m_sep; + prefix_t m_prefix; + postfix_t m_postfix; +}; + +template +class formatted_range + : public boost::iterator_range +{ + typedef formatted_holder holder_t; +public: + formatted_range(Iter first, Iter last, const holder_t& holder) + : boost::iterator_range(first, last) + , m_holder(holder) + { + } + + template + void write(OStream& out) const + { + Iter it(this->begin()); + out << m_holder.m_prefix; + if (it != this->end()) + { + out << *it; + for (++it; it != this->end(); ++it) + { + out << m_holder.m_sep << *it; + } + } + out << m_holder.m_postfix; + } + +private: + holder_t m_holder; +}; + +template< + typename SinglePassRange, + typename Sep, + typename Prefix, + typename Postfix +> +inline range_detail::formatted_range< + typename range_iterator::type, Sep, Prefix, Postfix +> +operator|( + const SinglePassRange& rng, + const range_detail::formatted_holder& holder +) +{ + typedef typename range_iterator::type iterator; + return range_detail::formatted_range( + boost::begin(rng), boost::end(rng), holder); +} + +template +std::basic_ostream& +operator<<( + std::basic_ostream& out, + const formatted_range& writer) +{ + writer.write(out); + return out; +} + + } // namespace range_detail + + namespace adaptors + { + +template +range_detail::formatted_holder +formatted(const Sep& sep, const Prefix& prefix, const Postfix& postfix) +{ + return range_detail::formatted_holder( + sep, prefix, postfix); +} + +template +range_detail::formatted_holder +formatted(const Sep& sep, const Prefix& prefix) +{ + return range_detail::formatted_holder(sep, prefix, '}'); +} + +template +range_detail::formatted_holder +formatted(const Sep& sep) +{ + return range_detail::formatted_holder(sep, '{', '}'); +} + +range_detail::formatted_holder +formatted() +{ + return range_detail::formatted_holder(',', '{', '}'); +} + +using range_detail::formatted_range; + +template +inline boost::range_detail::formatted_range< + typename boost::range_iterator::type, + Sep, Prefix, Postfix +> +format( + const SinglePassRange& rng, + const Sep& sep, + const Prefix& prefix, + const Postfix& postfix +) +{ + typedef typename boost::range_iterator::type + iterator_t; + + typedef boost::range_detail::formatted_range< + iterator_t, Sep, Prefix, Postfix> result_t; + + typedef boost::range_detail::formatted_holder + holder_t; + + return result_t(boost::begin(rng), boost::end(rng), + holder_t(sep, prefix, postfix)); +} + +template +inline boost::range_detail::formatted_range< + typename boost::range_iterator::type, + Sep, Prefix, char +> +format( + const SinglePassRange& rng, + const Sep& sep, + const Prefix& prefix) +{ + return adaptors::format(rng, sep, prefix, '}'); +} + +template +inline boost::range_detail::formatted_range< + typename boost::range_iterator::type, + Sep, char, char +> +format(const SinglePassRange& rng, const Sep& sep) +{ + return adaptors::format(rng, sep, '{', '}'); +} + +template +inline boost::range_detail::formatted_range< + typename boost::range_iterator::type, + char, char, char +> +format(const SinglePassRange& rng) +{ + return adaptors::format(rng, ',', '{', '}'); +} + + } // namespace adaptors +} // namespace boost + +#endif // include guard diff --git a/include/boost/range/adaptors.hpp b/include/boost/range/adaptors.hpp index 92062a9..0530c4d 100755 --- a/include/boost/range/adaptors.hpp +++ b/include/boost/range/adaptors.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/range/separated.hpp b/include/boost/range/separated.hpp deleted file mode 100644 index 556441e..0000000 --- a/include/boost/range/separated.hpp +++ /dev/null @@ -1,94 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2014. -// Use, modification and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_SEPARATED_HPP_INCLUDED -#define BOOST_RANGE_SEPARATED_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range_detail - { - -template -class output_stream_writer -{ -public: - output_stream_writer(Iter first, Iter last, Separator separator) - : m_first(first) - , m_last(last) - , m_separator(separator) - { - } - - template - void write(OStream& out) const - { - write_impl(out, m_first, m_last, m_separator); - } - -private: - template - static void write_impl( - OStream& out, Iter first, Iter last, Separator separator) - { - if (first != last) - { - out << *first; - for (++first; first != last; ++first) - { - out << separator << *first; - } - } - } - - Iter m_first; - Iter m_last; - Separator m_separator; -}; - -template -std::basic_ostream& -operator<<( - std::basic_ostream& out, - const output_stream_writer& writer) -{ - writer.write(out); - return out; -} - - } // namespace range_detail - - namespace range - { - -template -inline range_detail::output_stream_writer< - typename range_iterator::type, - Separator -> -separated(const Range& rng, Separator separator) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - return range_detail::output_stream_writer< - typename range_iterator::type, - Separator - >(boost::begin(rng), boost::end(rng), separator); -} - - } // namespace range -} // namespace boost - -#endif // include guard diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 4dae50d..5f84421 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -86,6 +86,8 @@ test-suite range : [ range-test adaptor_test/adjacent_filtered_example ] [ range-test adaptor_test/copied_example ] [ range-test adaptor_test/filtered_example ] + [ range-test adaptor_test/formatted ] + [ range-test adaptor_test/formatted_example ] [ range-test adaptor_test/indexed_example ] [ range-test adaptor_test/indirected_example ] [ range-test adaptor_test/map_keys_example ] @@ -204,7 +206,6 @@ test-suite range : [ range-test reverse_iterator ] [ range-test reverse_result_iterator ] [ range-test reversible_range ] - [ range-test separated ] [ range-test size_type ] [ range-test std_container ] [ range-test string ] diff --git a/test/adaptor_test/formatted.cpp b/test/adaptor_test/formatted.cpp new file mode 100644 index 0000000..b6c1783 --- /dev/null +++ b/test/adaptor_test/formatted.cpp @@ -0,0 +1,311 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost_range_test +{ + namespace + { + + template + std::string make_string(T x) + { + std::ostringstream result; + result << x; + return result.str(); + } + + template + std::string make_string(T1 x, T2 y) + { + std::ostringstream result; + result << x << y; + return result.str(); + } + +std::string reference_result(const std::vector& v, + const std::string& separator, + const std::string& prefix, + const std::string& postfix) +{ + std::ostringstream out; + out << prefix; + if (!v.empty()) + { + out << v.at(0); + std::vector::const_iterator it = v.begin(); + for (++it; it != v.end(); ++it) + { + out << separator << *it; + } + } + out << postfix; + + return out.str(); +} + +void test_formatted_0args_impl(const std::vector& v) +{ + std::ostringstream out1; + out1 << '[' << (v | boost::adaptors::formatted()) << ']'; + BOOST_CHECK_EQUAL(out1.str(), reference_result(v, ",", "[{", "}]")); + + std::ostringstream out2; + out2 << '[' << boost::adaptors::format(v) << ']'; + BOOST_CHECK_EQUAL(out2.str(), reference_result(v, ",", "[{", "}]")); + + std::ostringstream out3; + out3 << (v | boost::adaptors::formatted()); + BOOST_CHECK_EQUAL(out3.str(), reference_result(v, ",", "{", "}")); + + std::ostringstream out4; + out4 << boost::adaptors::format(v); + BOOST_CHECK_EQUAL(out4.str(), reference_result(v, ",", "{", "}")); +} + +template +void test_formatted_1arg_impl( + const std::vector& v, + const Sep& sep) +{ + const std::string ref_sep = make_string(sep); + std::ostringstream out1; + out1 << '[' << (v | boost::adaptors::formatted(sep)) << ']'; + + BOOST_CHECK_EQUAL(out1.str(), reference_result(v, ref_sep, "[{", "}]")); + + std::ostringstream out2; + out2 << '[' << boost::adaptors::format(v, sep) << ']'; + BOOST_CHECK_EQUAL(out2.str(), reference_result(v, ref_sep, "[{", "}]")); + + std::ostringstream out3; + out3 << (v | boost::adaptors::formatted(sep)); + BOOST_CHECK_EQUAL(out3.str(), reference_result(v, ref_sep, "{", "}")); + + std::ostringstream out4; + out4 << boost::adaptors::format(v, sep); + BOOST_CHECK_EQUAL(out4.str(), reference_result(v, ref_sep, "{", "}")); +} + +void test_formatted_1arg_impl(const std::vector& v) +{ + test_formatted_1arg_impl(v, ','); + test_formatted_1arg_impl(v, ' '); + test_formatted_1arg_impl(v, ":?"); +} + +template +void test_formatted_2args_impl( + const std::vector& v, + const Sep& sep, + const Prefix& prefix +) +{ + const std::string ref_sep = make_string(sep); + + std::ostringstream out1; + out1 << '[' << (v | boost::adaptors::formatted(sep, prefix)) << ']'; + BOOST_CHECK_EQUAL( + out1.str(), + reference_result(v, ref_sep, make_string('[', prefix), "}]")); + + std::ostringstream out2; + out2 << '[' << boost::adaptors::format(v, sep, prefix) << ']'; + BOOST_CHECK_EQUAL( + out2.str(), + reference_result(v, ref_sep, make_string('[', prefix), "}]")); + + std::ostringstream out3; + out3 << (v | boost::adaptors::formatted(sep, prefix)); + BOOST_CHECK_EQUAL( + out3.str(), + reference_result(v, ref_sep, make_string(prefix), "}")); + + std::ostringstream out4; + out4 << boost::adaptors::format(v, sep, prefix); + BOOST_CHECK_EQUAL( + out4.str(), + reference_result(v, ref_sep, make_string(prefix), "}")); +} + +void test_formatted_2args_impl(const std::vector& v) +{ + test_formatted_2args_impl(v, ',', '{'); + test_formatted_2args_impl(v, ':', '('); + test_formatted_2args_impl(v, ',', "{!"); + test_formatted_2args_impl(v, "#$", '{'); + test_formatted_2args_impl(v, "#$", "{!"); +} + +template +void test_formatted_3args_impl( + const std::vector& v, + const Sep& sep, + const Prefix& prefix, + const Postfix& postfix +) +{ + const std::string ref_sep = make_string(sep); + + std::ostringstream out1; + out1 << '[' << (v | boost::adaptors::formatted(sep, prefix, postfix)) + << ']'; + BOOST_CHECK_EQUAL( + out1.str(), + reference_result(v, ref_sep, make_string('[', prefix), + make_string(postfix, ']'))); +} + +void test_formatted_3args_impl(const std::vector& v) +{ + test_formatted_3args_impl(v, ',', '{', '}'); + test_formatted_3args_impl(v, ':', '(', ')'); + test_formatted_3args_impl(v, ',', '{', "!}"); + test_formatted_3args_impl(v, ',', "{!", '}'); + test_formatted_3args_impl(v, "#$", '{', '}'); + test_formatted_3args_impl< + const char[3], const char[3], const char[3] + >(v, "#$", "{!", "!}"); +} + +void test_formatted_impl(const std::vector& v) +{ + test_formatted_0args_impl(v); + test_formatted_1arg_impl(v); + test_formatted_2args_impl(v); + test_formatted_3args_impl(v); +} + +void test_formatted1() +{ + std::vector v; + for (boost::int32_t i = 0; i < 10; ++i) + v.push_back(i); + + test_formatted_impl(v); +} + +void test_formatted2() +{ + std::vector v; + v.push_back(3); + + test_formatted_impl(v); +} + +void test_formatted3() +{ + std::vector v; + + test_formatted_impl(v); +} + +void test_formatted4() +{ + std::vector v; + for (boost::int32_t i = 0; i < 5; ++i) + v.push_back(i); + + test_formatted_impl(v); +} + +struct udt_separator +{ +}; + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& out, udt_separator) +{ + return out << "[sep]"; +} + +void test_formatted5() +{ + std::vector v; + for (boost::int32_t i = 0; i < 5; ++i) + v.push_back(i); + + std::ostringstream out1; + out1 << (v | boost::adaptors::formatted(udt_separator())); + BOOST_CHECK_EQUAL(out1.str(), "{0[sep]1[sep]2[sep]3[sep]4}"); + + std::ostringstream out2; + out2 << boost::adaptors::format(v, udt_separator()); + BOOST_CHECK_EQUAL(out2.str(), "{0[sep]1[sep]2[sep]3[sep]4}"); +} + +// This test is already covered by the more complex code above. This +// code duplicates coverage to ensure that char literal arrays are handled +// correctly. I was particularly concerned that my test code above may pass +// erroneously by decaying a char literal to a pointer. This function makes +// it very plain that character literal strings work. +void test_formatted_empty() +{ + std::vector v; + + std::ostringstream out1; + out1 << (v | boost::adaptors::formatted()); + BOOST_CHECK_EQUAL(out1.str(), "{}"); + + std::ostringstream out2; + out2 << boost::adaptors::format(v); + BOOST_CHECK_EQUAL(out2.str(), "{}"); + + std::ostringstream out3; + out3 << (v | boost::adaptors::formatted(',')); + BOOST_CHECK_EQUAL(out3.str(), "{}"); + + std::ostringstream out4; + out4 << boost::adaptors::format(v, ','); + BOOST_CHECK_EQUAL(out4.str(), "{}"); + + std::ostringstream out5; + out5 << (v | boost::adaptors::formatted("#$")); + BOOST_CHECK_EQUAL(out5.str(), "{}"); + + std::ostringstream out6; + out6 << boost::adaptors::format(v, "#$"); + BOOST_CHECK_EQUAL(out6.str(), "{}"); + + std::ostringstream out7; + out7 << (v | boost::adaptors::formatted("", "12", "34")); + BOOST_CHECK_EQUAL(out7.str(), "1234"); + + std::ostringstream out8; + out8 << boost::adaptors::format(v, "", "12", "34"); + BOOST_CHECK_EQUAL(out8.str(), "1234"); +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite(int, char*[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE( "Boost.Range formatted test suite" ); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted1)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted2)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted3)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted4)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted5)); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted_empty)); + + return test; +} diff --git a/test/adaptor_test/formatted_example.cpp b/test/adaptor_test/formatted_example.cpp new file mode 100644 index 0000000..838a671 --- /dev/null +++ b/test/adaptor_test/formatted_example.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[formatted_example +#include +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void formatted_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::assign; + + std::vector input; + input += 1,2,3,4,5; + + std::cout << boost::adaptors::format(input) << std::endl; + + // Alternatively this can be written: + // std::cout << (input | boost::adaptors::formatted()) << std::endl; + +//= return 0; +//=} +//] + std::ostringstream test; + test << boost::adaptors::format(input); + + BOOST_CHECK_EQUAL(test.str(), "{1,2,3,4,5}"); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.formatted_example" ); + + test->add( BOOST_TEST_CASE( &formatted_example_test ) ); + + return test; +} diff --git a/test/separated.cpp b/test/separated.cpp deleted file mode 100644 index 680558d..0000000 --- a/test/separated.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2014. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ -// -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost_range_test -{ - namespace - { - -void test_separated1() -{ - std::vector v; - for (boost::int32_t i = 0; i < 10; ++i) - v.push_back(i); - - std::ostringstream out; - out << '{' << boost::range::separated(v, ',') << '}'; - - BOOST_CHECK_EQUAL(out.str(), "{0,1,2,3,4,5,6,7,8,9}"); -} - -void test_separated2() -{ - std::vector v; - v.push_back(3); - - std::ostringstream out; - out << '{' << boost::range::separated(v, ',') << '}'; - - BOOST_CHECK_EQUAL(out.str(), "{3}"); -} - -void test_separated3() -{ - std::vector v; - - std::ostringstream out; - out << '{' << boost::range::separated(v, ',') << '}'; - - BOOST_CHECK_EQUAL(out.str(), "{}"); -} - -void test_separated4() -{ - std::vector v; - for (boost::int32_t i = 0; i < 5; ++i) - v.push_back(i); - - std::ostringstream out; - out << '{' << boost::range::separated(v, "::") << '}'; - - BOOST_CHECK_EQUAL(out.str(), "{0::1::2::3::4}"); -} - -struct udt_separator -{ -}; - -template -inline std::basic_ostream& -operator<<(std::basic_ostream& out, udt_separator) -{ - return out << "[sep]"; -} - -void test_separated5() -{ - std::vector v; - for (boost::int32_t i = 0; i < 5; ++i) - v.push_back(i); - - std::ostringstream out; - out << '{' << boost::range::separated(v, udt_separator()) << '}'; - - BOOST_CHECK_EQUAL(out.str(), "{0[sep]1[sep]2[sep]3[sep]4}"); -} - - } // anonymous namespace -} // namespace boost_range_test - -boost::unit_test::test_suite* init_unit_test_suite(int, char*[] ) -{ - boost::unit_test::test_suite* test = - BOOST_TEST_SUITE( "Boost.Range separated test suite" ); - - test->add(BOOST_TEST_CASE(&boost_range_test::test_separated1)); - test->add(BOOST_TEST_CASE(&boost_range_test::test_separated2)); - test->add(BOOST_TEST_CASE(&boost_range_test::test_separated3)); - test->add(BOOST_TEST_CASE(&boost_range_test::test_separated4)); - test->add(BOOST_TEST_CASE(&boost_range_test::test_separated5)); - - return test; -}