Fisher Sun 🎣

We have println at home

cxx

While working through Crafting Interpreters in C++, I wanted to explore as many modern C++ features as I could. One of the features I was the most hyped for was print and println.

Finally, a normal way to print things! I provided std::formatter specializations for my TokenType and Token classes, and in my main.cpp I excitedly typed:

std::println

only for my IDE to not provide an autocompletion that would include the header file.

Indeed, I did not have the <print> header on my machine.

I figured my C++ toolchain was too old and didn’t have support for it yet. “Ah, no problem,” I thought, “this is what I have mise for.” But trying to install a newer clang with mise resulted in mise trying to compile it from source, which I didn’t want to sit around and wait for.

So I glumly stuck with using std::cout and std::format as per this StackOverflow answer.

std::cout << std::format("{}", token) << std::endl;

But this left me feeling unsatisfied. It was so verbose.

Maybe I could just implement print and println myself.

I copied the signatures of print and println from cppreference and implemented them like so:

#include <format>
#include <iostream>
#include <iterator>
template<class... Args>
void print(std::format_string<Args...> fmt, Args &&... args) {
static std::ostream_iterator<char> out(std::cout);
std::format_to(out, fmt, args...);
}
template<class... Args>
void println(std::format_string<Args...> fmt, Args &&... args) {
print(fmt, args...);
std::cout << std::endl;
}
  1. Based on this other StackOverflow answer.
  2. Flush cout on every new line, just like Java’s System.out.println.

This worked! In my main.cpp, I could now do

println("{}", token);

My implementation is far less complete than LLVM’s, but it does the job for my simple tree walk interpreter, and I’m happy with it.