A header-only IO library implemented in C++20, internally a wrapper over stdio.
The library is under development and subject to change. Contributions are welcome (but keep in mind that I’m very opinionated). You can also log an issue if you spot a bug or if you want a particular feature not already listed in TODO.
- Clean and consistent interface
- Pretty-printing STL containers and pointers
- Initializing (multiple) variables on read (no mutation necessary)
- No
sync_with_stdio, so should be faster thaniostream - No runtime format strings, so might be faster than
stdio
Add it to your Git project as a submodule:
git submodule add git@github.com:natewind/cleario.gitOr simply clone:
git clone --recurse-submodules git@github.com:natewind/cleario.gitInclude the public interface:
#include "cleario/include.hpp"To read a value of type T:
auto const x = clear::read<T>(); // x: TTo read multiple values of types Ts:
auto const xs = clear::read<Ts...>(); // xs: std::tuple<Ts...>If the end of the file is reached or there are no values of type(s) T/Ts to read, the behaviour is undefined.
To read safely:
// maybe_x: std::optional<T>
auto const maybe_x = clear::safe_read<T>();
// maybe_xs: std::optional<std::tuple<Ts...>>
auto const maybe_xs = clear::safe_read<Ts...>();auto const [a, b] = clear::read<char, char>(); // qwauto const [t, f] = clear::read<bool, bool>(); // True FalseIntegral types (except for char) in different bases:
auto const a = clear::read<int>(); // 123
auto const b = clear::read<clear::bin<int>>(); // 0b1111011
auto const c = clear::read<clear::oct<int>>(); // 0o173
auto const d = clear::read<clear::hex<int>>(); // 0x7bExplicit decimal base to read an integer into char:
auto const e = clear::read<clear::dec<char>>(); // 123If a read fails, characters from the input stream are consumed until the one that induced the failure.
To print one or more values without a newline:
clear::print("Helo, World! ", 42, ' ', true); // Hello, World! 42 TrueWith a newline:
clear::println("Helo, World! ", 42, ' ', true); // Hello, World! 42 TrueTo flush stdout:
clear::flush();All three functions return true on success and false on failure. print / println aborts after the first unsuccessful write.
clear::println('a', 'b', 'c'); // abcchar const*std::stringstd::string_view
auto const str = std::string("Qwerty");
clear::println(str); // Qwertyclear::println(true, ' ', false); // True FalseIntegral types (except for char) in different bases:
clear::println(150); // 150
clear::println(clear::bin {150}); // 0b10010110
clear::println(clear::oct {150}); // 0o226
clear::println(clear::hex {150}); // 0x96Explicit decimal base to print char as an integer:
clear::println(clear::dec {'q'}); // 113floatdoublelong double
Chooses the shortest notation between std::chars_format::fixed and std::chars_format::scientific:
clear::println(3.14); // 3.14
clear::println(-0.0000000005); // -5e-10T*std::unique_ptrstd::shared_ptr
auto const x = 5;
auto const ptr = static_cast<void*>(&x);
clear::println(&x); // <int object at 0x7ffcb52c6c54>
clear::println(ptr); // <object at 0x7ffcb52c6c54>clear::println(std::optional<int> {}); // None
clear::println(std::optional {12}); // Some(12)clear::println(std::tuple(5, false, "qwerty")); // (5, False, qwerty)T[]std::arraystd::vectorstd::dequestd::forward_liststd::list
auto const vec = std::vector {1, 2, 3, 4, 5};
clear::println(vec); // [1, 2, 3, 4, 5]std::setstd::multisetstd::unordered_setstd::unordered_multiset
auto const set = std::set {1, 2, 3, 4, 5};
clear::println(set); // {1, 2, 3, 4, 5}std::mapstd::multimapstd::unordered_mapstd::unordered_multimap
auto const map = std::unordered_map {{"a", 1}, {"b", 2}, {"c", 3}, {"d", 4}, {"e", 5}};
clear::println(map); // {e: 5, c: 3, b: 2, d: 4, a: 1}Consider a type:
struct Point { int x, y; };To make it printable, implement print for it by calling print on already printable types:
template <>
auto clear::io::print(Point const &point) -> bool
{
return print('(', point.x, ", ", point.y, ')');
}Try it out:
clear::println(Point {3, 4}); // (3, 4)To open a file:
auto file = clear::open("file.txt", "w");The access modes are the same ones used with std::fopen (the default is "r+"). Files are movable (but not copyable) and close automatically when leaving the scope.
To open a file safely (because it can fail):
auto maybe_file = clear::safe_open("maybe_file.txt", "w"); // returns std::optionalTo write to a file, simply use print / println and flush as member functions:
file.println("Helo, World! ", 42, ' ', true);
if (maybe_file)
maybe_file->println("Helo, World! ", 42, ' ', true);To read from a file, use read / safe_read as a member function:
auto const [a, b] = open("input.txt").read<char, int>();