Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstddef>
- #include <iomanip>
- #include <iostream>
- #include <list>
- #include <map>
- #include <set>
- #include <string>
- #include <utility>
- #include <vector>
- #include <boost/iterator/iterator_adaptor.hpp>
- #include <boost/range.hpp>
- #include <boost/range/adaptor/argument_fwd.hpp>
- #include <boost/tuple/tuple.hpp>
- #include <boost/tuple/tuple_io.hpp>
- #include <boost/units/quantity.hpp>
- #include <boost/units/systems/si.hpp>
- #include <boost/units/systems/si/io.hpp>
- #include "measurement.hpp" // An uncertain type called measure.
- #include "rangeio" // (I'm reusing the version of range I/O already written for the std proposal)
- using std::write_all;
- // BEGIN stuff needed for column separator /////////////////////////////////////
- /*
- * This is all for a special delimiter that adds a new line after a column is filled.
- */
- template <typename Delimiter>
- struct column_separator_printer_t
- {
- column_separator_printer_t(Delimiter&& d, std::size_t n) :
- d_{std::forward<Delimiter>(d)}, colcount_{n}, i_{0}
- {}
- Delimiter&& d_;
- std::size_t const colcount_;
- mutable std::size_t i_;
- };
- template <typename Delimiter, typename CharT, typename Traits>
- auto operator<<(std::basic_ostream<CharT, Traits>& o, column_separator_printer_t<Delimiter> const& c) ->
- std::basic_ostream<CharT, Traits>&
- {
- o << c.d_;
- if (++c.i_ == c.colcount_)
- {
- o << '\n';
- c.i_ = 0;
- }
- return o;
- }
- template <typename Delimiter>
- auto column_sep(Delimiter&& d, std::size_t n)
- {
- return column_separator_printer_t<Delimiter>{std::forward<Delimiter>(d), n};
- }
- // END stuff needed for column separator ///////////////////////////////////////
- // BEGIN stuff needed for column major ordering ////////////////////////////////
- /*
- * This is all for a range adaptor that reorders the elements in a range into column-major order.
- */
- template <typename ForwardIterator>
- struct column_major_order_iterator :
- boost::iterator_adaptor<column_major_order_iterator<ForwardIterator>, ForwardIterator>
- {
- column_major_order_iterator() = default;
- column_major_order_iterator(ForwardIterator i, ForwardIterator b, ForwardIterator e, std::size_t c) :
- boost::iterator_adaptor<column_major_order_iterator<ForwardIterator>, ForwardIterator>{i},
- begin_{b}, end_{e}, row_current_{b}
- {
- auto const num_elements = std::size_t(std::distance(begin_, end_));
- stride_ = (num_elements / c) + ((num_elements % c) ? 1 : 0);
- }
- void increment()
- {
- auto& i = this->base_reference();
- auto const d = std::size_t(std::distance(i, end_));
- auto const row_end = std::next(begin_, stride_);
- if (d > stride_)
- std::advance(i, stride_);
- else if ((row_current_ != row_end) && (++row_current_ != row_end))
- i = row_current_;
- else
- i = end_;
- }
- ForwardIterator begin_;
- ForwardIterator end_;
- ForwardIterator row_current_;
- std::size_t stride_;
- };
- template <typename Range>
- struct column_major_order_range :
- boost::iterator_range<column_major_order_iterator<typename boost::range_iterator<Range>::type>>
- {
- column_major_order_range(Range& r, std::size_t colcount) :
- boost::iterator_range<column_major_order_iterator<typename boost::range_iterator<Range>::type>>{
- column_major_order_iterator<typename boost::range_iterator<Range>::type>{boost::begin(r), boost::begin(r), boost::end(r), colcount},
- column_major_order_iterator<typename boost::range_iterator<Range>::type>{boost::end(r), boost::begin(r), boost::end(r), colcount}
- }
- {}
- };
- template <typename T>
- struct column_major_order_holder : boost::range_detail::holder<std::size_t>
- {
- column_major_order_holder(T colcount) :
- boost::range_detail::holder<std::size_t>{std::size_t(colcount)}
- {}
- };
- static auto column_major_ordered = boost::range_detail::forwarder<column_major_order_holder>();
- template <typename ForwardRange, typename T>
- inline auto operator|(ForwardRange& r, column_major_order_holder<T> const& f)
- {
- return column_major_order_range<ForwardRange>(r, f.val);
- }
- template <typename ForwardRange, typename T>
- inline auto operator|(ForwardRange const& r, column_major_order_holder<T> const& f)
- {
- return column_major_order_range<ForwardRange const>(r, f.val);
- }
- /*
- * This is all for a special delimiter that adds new lines to print the elements in columns,
- * filling up the columns before the rows.
- */
- template <typename Delimiter>
- struct column_major_separator_printer_t
- {
- column_major_separator_printer_t(Delimiter&& d, std::size_t total, std::size_t colcount) :
- d_{std::forward<Delimiter>(d)}, total_{total}, colcount_{colcount},
- full_rows_{(total / colcount) + ((total % colcount) ? 1 : 0) - (total % colcount)},
- i_{0}
- {}
- Delimiter&& d_;
- std::size_t const total_;
- std::size_t const colcount_;
- std::size_t const full_rows_;
- mutable std::size_t i_;
- };
- template <typename Delimiter, typename CharT, typename Traits>
- auto operator<<(std::basic_ostream<CharT, Traits>& o, column_major_separator_printer_t<Delimiter> const& c) ->
- std::basic_ostream<CharT, Traits>&
- {
- o << c.d_;
- if (++c.i_ <= (c.full_rows_ * c.colcount_))
- {
- if ((c.i_ % c.colcount_) == 0)
- o << '\n';
- }
- else
- {
- auto const i = c.i_ - (c.full_rows_ * c.colcount_);
- if ((i % (c.colcount_ - 1)) == 0)
- o << '\n';
- }
- return o;
- }
- template <typename Range, typename Delimiter>
- auto column_major_sep(Range const& r, Delimiter&& d, std::size_t n)
- {
- using std::begin;
- using std::end;
- return column_major_separator_printer_t<Delimiter>{std::forward<Delimiter>(d), std::size_t(std::distance(begin(r), end(r))), n};
- }
- // END stuff needed for column major ordering //////////////////////////////////
- // Not generally a great idea, but it was in the original code, so...
- namespace std {
- template <typename T1, typename T2, typename CharT, typename Traits>
- auto operator<<(std::basic_ostream<CharT, Traits>& o, std::pair<T1, T2> const& p) ->
- std::basic_ostream<CharT, Traits>&
- {
- return o << p.first << ' ' << p.second;
- }
- } // namespace std
- auto main() -> int
- {
- using namespace boost::units;
- using namespace boost::units::si;
- int test[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- double testd[] = { 1., 2., 3., 4., 5., 6., 7., 8., 9., 10. };
- // Note: the original code creates a separator_printer named p1, then reuses
- // it over and over. I didn't do that - I used multiple calls to write_all,
- // so the delimiter has to be repeated.
- // If you want to avoid repeating the delimiter, then you can do:
- // auto p1 = [](auto const& r) { return write_all(r, ", "); };
- // (possibly with a universal reference and std::forward). Then replace all:
- // std::cout << write_all(XXX, ", ") << '\n';
- // with:
- // std::cout << p1(XXX) << '\n';
- // and so on.
- std::cout << write_all(test, ", ") << '\n'; // 1,2,3,4,5,6,7,8,9,10
- // This is the version with the automatic newline... which is unnecessary now because it's all one statement.
- // If you really want an automatic newline, you can wrap write_all in a lambda that appends it.
- std::cout << write_all(test, ", ") << "|\n"; // 1,2,3,4,5,6,7,8,9,10|
- // If you need to reuse the prefix/suffix/delimiter combo, you could easily make a lambda
- std::cout << "int[10] = {" << write_all(test, ", ") << "};\n"; // int[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
- std::cout << write_all(test, "___") << '\n'; // 1___2___3___4___5___6___7___8___9___10
- std::cout << write_all(testd, ", ") << '\n'; // 1,2,3,4,5,6,7,8,9,10
- std::cout.precision(5);
- std::cout << std::showpos << std::showpoint << '\n';
- std::cout << write_all(testd, ", ") << '\n'; // +1.0000,+2.0000,+3.0000,+4.0000,+5.0000,+6.0000,+7.0000,+8.0000,+9.0000,+10.000
- std::cout << std::noshowpos << '\n'; // Switch off fancy +.
- // NOTE: When I ran the original program, i didn't get the expected output - everything was in metres; units weren't scaled.
- // This code *does* scale the units.
- quantity<length> testq[] = {2345.6 * meters, 123.4 * meters, 0.0123 * meters};
- std::cout << engineering_prefix << write_all(testq, ", ") << '\n'; // 2.3456 km, 123.40 m, 12.300 mm
- // Again, the units weren't scaled in the original code. I didn't scale them here.
- quantity<length, measurement<double> > testqu[] = {measurement<double>(45210.0, 1234.0) * meters, measurement<double>(789, 2.5) * meters, measurement<double>(0.000567,2.34e-5) * meters};
- std::cout << write_all(testqu, ", ") << '\n'; // 45210.(+/-1234.0) m, 789.00(+/-2.5000) m, 0.00056700(+/-2.3400e-05) m
- const char* testCstring[] = {"one", "two", "three", "four","five", "six","seven","eight", "nine", "ten"};
- std::cout << write_all(testCstring, ", ") << '\n'; // Type is now a C string.
- std::string teststring[] = {"ONE", "TWO", "THREE", "FOUR","FIVE", "SIX","SEVEN","EIGHT", "NINE", "TEN"};
- std::cout << write_all(teststring, ", ") << '\n'; // Type is now a std::string.
- // Now some other sequence printers.
- // Requires some extra code (~30 lines, see above main())
- std::cout << write_all(test, column_sep(',', 4)) << '\n'; // 1,2,3,4, and then 5,6,7,8, and then 9,10
- // Requires some extra code (~100 lines see above main())
- std::cout << std::setw(16) << write_all(test | column_major_ordered(4), column_major_sep(test, "", 4)) << '\n' << '\n'; // 1 4 7 10 then 2 5 8, then 3 6 9
- std::vector<double> testv(testd, testd + sizeof(testd)/ sizeof(testd[0]));
- std::cout << write_all(testv, ", ") << '\n'; // 1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.000
- std::list<double> testl(testd, testd + sizeof(testd)/ sizeof(testd[0]));
- std::cout << write_all(testl, column_sep(",", 4)) << '\n'; // 1.0000,2.0000,3.0000,4.0000,
- // 5.0000,6.0000,7.0000,8.0000,
- // 7.0000
- std::set<double> tests;
- tests.insert(3.);
- tests.insert(4.);
- tests.insert(5.);
- tests.insert(6.);
- tests.insert(7.);
- std::cout << write_all(tests, column_sep(",", 4)) << '\n'; // 3.0000,4.0000,5.0000,6.0000,
- // 7.0000
- std::cout << std::noshowpoint;
- std::map<int, double> my_map;
- my_map.insert(std::make_pair(1, 9.9));
- my_map.insert(std::make_pair(2, 8.8));
- my_map.insert(std::make_pair(3, 7.7));
- my_map.insert(std::make_pair(4, 6.6));
- std::cout << write_all(my_map, column_sep(",", 4)) << '\n' << '\n'; // 1, 9.9,2, 8.8,3, 7.7,4, 6.6
- using boost::tuples::tuple;
- using boost::tuples::make_tuple;
- tuple<int, double, std::string> ids1(23, 99.9, "my_string"); // Construct a tuple.
- // But convenient to use a typedef for the tuple type.
- typedef tuple<int, double, std::string> my_tuple_t;
- my_tuple_t ids2(42, 3.1459, "other_string"); // Construct another using typedef.
- std::vector<my_tuple_t> testtup;
- testtup.push_back(ids1);
- testtup.push_back(ids2);
- my_tuple_t ids3(43, 2.8, "third_string"); // Construct yet another also using typedef.
- testtup.push_back(ids3);
- std::cout << write_all(testtup, column_sep(",", 4)) << '\n' << '\n'; // (23 99.900 my_string),(42 3.1459 other_string)
- using boost::tuples::set_open;
- using boost::tuples::set_delimiter;
- using boost::tuples::set_close;
- std::cout << set_open('[') << set_delimiter('_') << set_close(']') <<
- "= {" << write_all(testtup, ", ") << "};\n";
- // = {[23_99.900_my_string], [42_3.1459_other_string], [43_2.8000_third_string]};
- std::cout << "= {" << write_all(testtup, ",\n ") << "};\n";
- // = {[23_99.900_my_string],
- // [42_3.1459_other_string],
- // [43_2.8000_third_string]};
- }
- /*
- Output:
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10|
- int[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
- 1___2___3___4___5___6___7___8___9___10
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
- +1.0000, +2.0000, +3.0000, +4.0000, +5.0000, +6.0000, +7.0000, +8.0000, +9.0000, +10.000
- 2.3456 km, 123.40 m, 12.300 mm
- 45210.(+/-1234.0) m, 789.00(+/-2.5000) m, 0.00056700(+/-2.3400e-05) m
- one, two, three, four, five, six, seven, eight, nine, ten
- ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN
- 1,2,3,4,
- 5,6,7,8,
- 9,10
- 1 4 7 10
- 2 5 8
- 3 6 9
- 1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.000
- 1.0000,2.0000,3.0000,4.0000,
- 5.0000,6.0000,7.0000,8.0000,
- 9.0000,10.000
- 3.0000,4.0000,5.0000,6.0000,
- 7.0000
- 1 9.9,2 8.8,3 7.7,4 6.6
- (23 99.9 my_string),(42 3.1459 other_string),(43 2.8 third_string)
- = {[23_99.9_my_string], [42_3.1459_other_string], [43_2.8_third_string]};
- = {[23_99.9_my_string],
- [42_3.1459_other_string],
- [43_2.8_third_string]};
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement