Search code examples
c++c++11formattingostreamc++23

Can I use an std::ostream to print into a given buffer?


I have a given buffer of characters (maybe even the buffer backing an std::string, but never mind that). I want to print into that buffer using an std::ostream, i.e. I want to be able to write:

span<char> my_buffer = get_buffer();
auto my_os = /* magic */;
static_assert(
   std::is_base_of<std::basic_ostream<char>,decltype(my_os)>::value,
   "magic failed");
my_os << "hello" << ',' << 123 << '\0';
std::cout << my_buffer << '\n';

and get:

hello,123

on the standard output.

Note: C++11 if possible, and please mention the language standard you're using. (And yes, I know C++11 doesn't have spans.)


Solution

  • (Thank @BoP and @T.C. for the two parts of this solution)

    This can be done... if you're willing to use a deprecated C++ construct: std:ostrstream.

    #include <strstream>
    #include <iostream>
    
    int main() {
        const size_t n = 20;
        char my_buffer[n];
        std::ostrstream my_os(my_buffer, n);
        my_os << "hello" << ',' << 123 << '\0';
        std::cout << my_buffer << '\n';
    }
    

    Notes about this code:

    1. It works (GodBolt)
    2. It is valid C++98! ... of course I had to let go of std::span, auto type inference etc. It's also valid C++11 and later standards.
    3. This will construct an std::strstreambuf, which is what an std::ostrstream uses directly, from your buffer of chars.

    (see this on GodBolt)

    Unfortunately, with the deprecation of std::ostrstream, we were left with no fully-valid alternative up to, and including, C++20. You would need to implement a custom std::basic_streambuf, and assign it to an std::ostream. :-(

    But in C++23 - you are luck! The standard library does offer exactly what you asked for: std::spanstream: A std::ostream backed by a span of char's which it is given at construction.