ostream_joiner.hpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. Copyright 2019 Glen Joseph Fernandes
  3. (glenjofe@gmail.com)
  4. Distributed under the Boost Software License, Version 1.0.
  5. (http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. #ifndef BOOST_IO_OSTREAM_JOINER_HPP
  8. #define BOOST_IO_OSTREAM_JOINER_HPP
  9. #include <boost/config.hpp>
  10. #include <ostream>
  11. #include <string>
  12. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  13. #if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
  14. #include <type_traits>
  15. #endif
  16. #include <utility>
  17. #endif
  18. namespace boost {
  19. namespace io {
  20. namespace detail {
  21. #if !defined(BOOST_NO_CXX11_ADDRESSOF)
  22. template<class T>
  23. inline T*
  24. osj_address(T& o)
  25. {
  26. return std::addressof(o);
  27. }
  28. #else
  29. template<class T>
  30. inline T*
  31. osj_address(T& obj)
  32. {
  33. return &obj;
  34. }
  35. #endif
  36. } /* detail */
  37. template<class Delim, class Char = char,
  38. class Traits = std::char_traits<Char> >
  39. class ostream_joiner {
  40. public:
  41. typedef Char char_type;
  42. typedef Traits traits_type;
  43. typedef std::basic_ostream<Char, Traits> ostream_type;
  44. typedef std::output_iterator_tag iterator_category;
  45. typedef void value_type;
  46. typedef void difference_type;
  47. typedef void pointer;
  48. typedef void reference;
  49. ostream_joiner(ostream_type& output, const Delim& delim)
  50. : output_(detail::osj_address(output))
  51. , delim_(delim)
  52. , first_(true) { }
  53. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  54. ostream_joiner(ostream_type& output, Delim&& delim)
  55. : output_(detail::osj_address(output))
  56. , delim_(std::move(delim))
  57. , first_(true) { }
  58. #endif
  59. template<class T>
  60. ostream_joiner& operator=(const T& value) {
  61. if (!first_) {
  62. *output_ << delim_;
  63. }
  64. first_ = false;
  65. *output_ << value;
  66. return *this;
  67. }
  68. ostream_joiner& operator*() BOOST_NOEXCEPT {
  69. return *this;
  70. }
  71. ostream_joiner& operator++() BOOST_NOEXCEPT {
  72. return *this;
  73. }
  74. ostream_joiner& operator++(int) BOOST_NOEXCEPT {
  75. return *this;
  76. }
  77. private:
  78. ostream_type* output_;
  79. Delim delim_;
  80. bool first_;
  81. };
  82. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
  83. !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
  84. template<class Char, class Traits, class Delim>
  85. inline ostream_joiner<typename std::decay<Delim>::type, Char, Traits>
  86. make_ostream_joiner(std::basic_ostream<Char, Traits>& output, Delim&& delim)
  87. {
  88. return ostream_joiner<typename std::decay<Delim>::type, Char,
  89. Traits>(output, std::forward<Delim>(delim));
  90. }
  91. #else
  92. template<class Char, class Traits, class Delim>
  93. inline ostream_joiner<Delim, Char, Traits>
  94. make_ostream_joiner(std::basic_ostream<Char, Traits>& output,
  95. const Delim& delim)
  96. {
  97. return ostream_joiner<Delim, Char, Traits>(output, delim);
  98. }
  99. #endif
  100. } /* io */
  101. } /* boost */
  102. #endif