Skip to content
Snippets Groups Projects
Commit 4c669bb4 authored by Recolic Keghart's avatar Recolic Keghart
Browse files

Merge branch 'stdio-allow-nonconst-begin' into 'master'

bug fix for rlib::printable_iter, to allow object that only has nonconst begin() to get printable_iter

See merge request root/rlib!1
parents 02808cda bb4854fc
No related branches found
No related tags found
No related merge requests found
#ifndef R_CXX20_REQUIRED
#define R_CXX20_REQUIRED
#include <rlib/sys/os.hpp>
#if RLIB_CXX_STD <= 2017
#error This file requires compiler and library support \
for the ISO C++ 2020 standard. This support must be enabled \
with the -std=c++20 or -std=c++2a compiler options.
#endif
#endif
...@@ -102,19 +102,22 @@ namespace rlib { ...@@ -102,19 +102,22 @@ namespace rlib {
template <typename Iterable, typename Printable> template <typename Iterable, typename Printable>
struct _printable_iterable : private std::pair<Iterable, Printable> { struct _printable_iterable : private std::pair<Iterable, Printable> {
using std::pair<Iterable, Printable>::pair; using std::pair<Iterable, Printable>::pair;
const Iterable &arg() const {return std::pair<Iterable, Printable>::first;} using _printable_iterable_tag = void;
const Printable &spliter() const {return std::pair<Iterable, Printable>::second;} Iterable &arg() & {return std::pair<Iterable, Printable>::first;}
Printable &spliter() & {return std::pair<Iterable, Printable>::second;}
Iterable &&arg() && {return std::pair<Iterable, Printable>::first;}
Printable &&spliter() && {return std::pair<Iterable, Printable>::second;}
const Iterable &arg() const & {return std::pair<Iterable, Printable>::first;}
const Printable &spliter() const & {return std::pair<Iterable, Printable>::second;}
}; };
template <typename FirstT, typename SecondT> using FirstOf = FirstT;
} }
// 2 more interfaces... // more interfaces...
template <typename Iterable, typename Printable> template <typename Iterable, typename Printable = char>
const impl::_printable_iterable<Iterable, Printable> printable_iter(Iterable arg, Printable spliter) { auto printable_iter(Iterable &&arg, Printable spliter = ' ') -> impl::_printable_iterable<typename std::decay<Iterable>::type, Printable> {
return impl::_printable_iterable<Iterable, Printable>(arg, spliter); // TODO: avoid the extra copy while passing lvalue reference on constructing return value obj.
} return impl::_printable_iterable<typename std::decay<Iterable>::type, Printable>(std::forward<Iterable>(arg), spliter);
template <typename Iterable>
const impl::_printable_iterable<Iterable, char> printable_iter(Iterable arg) {
return impl::_printable_iterable<Iterable, char>(arg, ' ');
} }
inline bool sync_with_stdio(bool sync = true) noexcept { inline bool sync_with_stdio(bool sync = true) noexcept {
...@@ -124,8 +127,8 @@ namespace rlib { ...@@ -124,8 +127,8 @@ namespace rlib {
return impl::enable_endl_flush() = enable; return impl::enable_endl_flush() = enable;
} }
// Implements. // Implements below ---------------------
template < class CharT, class Traits > template <typename CharT, typename Traits>
inline std::basic_ostream<CharT, Traits>& endl(std::basic_ostream<CharT, Traits>& os) { inline std::basic_ostream<CharT, Traits>& endl(std::basic_ostream<CharT, Traits>& os) {
os << RLIB_IMPL_ENDLINE; os << RLIB_IMPL_ENDLINE;
if(impl::enable_endl_flush()) if(impl::enable_endl_flush())
...@@ -215,12 +218,22 @@ namespace rlib { ...@@ -215,12 +218,22 @@ namespace rlib {
} }
} // end namespace rlib } // end namespace rlib
template <typename Iterable, typename Printable> // auto-deduct const/nonconst left/right value ref.
std::ostream& operator<< (std::ostream& stream, const rlib::impl::_printable_iterable<Iterable, Printable> &p) { // For C++20 std::view, it doesn't have a `begin()` method for const lvalue ref. So we have to support
for(auto val : p.arg()) { // passing rvalue from rlib::printable_iter() to rlib::impl::_printable_iterable to operator<<
stream << val << p.spliter(); // Instead of writing 3 overloads here, let us deduce automatically.
} template <typename PrintableIterableT>
return stream; rlib::impl::FirstOf<std::ostream&, typename std::decay<PrintableIterableT>::type::_printable_iterable_tag> operator<< (std::ostream& stream, PrintableIterableT &&p) {
for(auto val : p.arg())
stream << val << p.spliter();
return stream;
} }
// // Old version, for backup
// template <typename Iterable, typename Printable>
// std::ostream& operator<< (std::ostream& stream, rlib::impl::_printable_iterable<Iterable, Printable> &&p) {
// for(auto val : p.arg())
// stream << val << p.spliter();
// return stream;
// }
#endif #endif
...@@ -82,7 +82,12 @@ TEST_CASE("stdio.hpp") { ...@@ -82,7 +82,12 @@ TEST_CASE("stdio.hpp") {
std::stringstream ss1, ss2; std::stringstream ss1, ss2;
rlib::println(ss1, rlib::printable_iter(v, rlib::printable_iter(v))); rlib::println(ss1, rlib::printable_iter(v, rlib::printable_iter(v)));
rlib::print(ss2, rlib::printable_iter(v, rlib::printable_iter(v))); rlib::print(ss2, rlib::printable_iter(v, rlib::printable_iter(v)));
rlib::println(ss1.str() == answer + '\n', ss2.str() == answer); rlib::println(ss1.str() == answer + RLIB_IMPL_ENDLINE, ss2.str() == answer);
const rlib_test_iterable vc{1.2, 6.666, 12, -11.11};
std::stringstream ssvc;
rlib::println(ssvc, rlib::printable_iter(vc, rlib::printable_iter(vc)));
REQUIRE(ssvc.str() == answer + RLIB_IMPL_ENDLINE);
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment