std::format handles user-defined type if it's iterable‽

std::format handles user-defined type if it's iterable‽

I updated some older code to use std::format, and was surprised to discover that it worked despite that fact that I had forgotten to provide a std::formatter specialization for that type.

I immediately made a small test program to try to reproduce this, but those always got a compile-time error as I expected.

After hours of debugging, I figured out that, if the custom type has public begin and end methods, the library will format the sequence as a comma-separated list enclosed in square brackets.

Q: Is this a standards-defined feature of std::format or an implementation bug? (Or something else?)

Here's a self-contained repro:

#include <array>
#include <print>

class MyType {
    public:
        MyType() : m_values{1, 2, 3, 4} {}

        using internal_type = std::array<int, 4>;
        using const_iterator = typename internal_type::const_iterator;

        const_iterator cbegin() const { return m_values.cbegin(); }
        const_iterator cend()   const { return m_values.cend();   }
        const_iterator begin()  const { return cbegin(); }
        const_iterator end()    const { return cend();   }

    private:
        internal_type m_values;
};

int main() {
    MyType foo;
    // Since MyType is a user-defined type, I would not
    // expect this print statement to compile without a
    // specialization of std::formatter, but because
    // it's iterable, it prints: "foo = [1, 2, 3, 4]\n".
    std::print("foo = {}\n", foo);
    return 0;
}

I'm using MS VC++ from Visual Studio 17.12.15 and compiling with /std:c++latest.

Answer

The standard library defines a std::formatter specialization for ranges starting in C++23:

template< ranges::input_range R, class CharT >
    requires (std::format_kind<R> != std::range_format::disabled) &&
              std::formattable<ranges::range_reference_t<R>, CharT>
struct formatter<R, CharT>;

Enjoyed this article?

Check out more content on our blog or follow us on social media.

Browse more articles