Formatting Library (std::format(), std::print())

Basics

#include <format>
#include <gtest/gtest.h>

TEST(format_suite, basics)
{
    ASSERT_EQ(std::format("The answer is {}", 42), "The answer is 42");

    ASSERT_EQ(std::format("There are two answers: {} and {}", 42, 7), "There are two answers: 42 and 7");

    // same with more syntax, but omitting position and formatting parameters
    ASSERT_EQ(std::format("The answer is {:}", 42), "The answer is 42");
}

Positional Arguments

#include <format>
#include <gtest/gtest.h>

TEST(format_suite, positional)
{
    ASSERT_EQ(std::format("The answer is {0}, evil {1}, answer again {0}", 42, 666), "The answer is 42, evil 666, answer again 42");
}

Not Consuming All Arguments Is Not An Error

#include <format>
#include <gtest/gtest.h>

TEST(format_suite, not_consuming_all_args_is_not_an_error)
{
    ASSERT_EQ(std::format("The answer is {}", 42, "and not 666"), "The answer is 42");
}

Escaping Curly Braces

#include <format>
#include <gtest/gtest.h>

TEST(format_suite, escape_curly)
{
    ASSERT_EQ(std::format("{{"), "{");
    ASSERT_EQ(std::format("}}"), "}");
    ASSERT_EQ(std::format("{{}}"), "{}");
}

C-Style Escapes

#include <format>
#include <gtest/gtest.h>

TEST(format_suite, c_style_escapes)
{
    ASSERT_EQ(std::format("\t\n\\"), "\t\n\\");
}

Format String

fill-and-align (optional) sign (optional) #(optional) 0(optional) width (optional) precision (optional) L(optional) type (optional)

Fill And Align: Basics

  • Datatype statically deduced

  • ⟶ Type specific fill and align

#include <format>
#include <gtest/gtest.h>

// like python, but statically deduced
TEST(format_suite, fill_and_align__datatype_deduced_from_parameter)
{
    // explicit fill/align
    ASSERT_EQ(std::format("{:x<6}", 42), "42xxxx");
    ASSERT_EQ(std::format("{:x<6}", "42"), "42xxxx");

    // omitting fill/align -> space with type specific align: numeric-right/str-left
    ASSERT_EQ(std::format("{:6}", 42), "    42");
    ASSERT_EQ(std::format("{:6}", "42"), "42    ");

    // centering
    ASSERT_EQ(std::format("{:x^6}", "42"), "xx42xx");
}

Fill And Align: Explicit Datatype

#include <format>
#include <gtest/gtest.h>

TEST(format_suite, fill_and_align__explicit_datatype)
{
    char c = 'x'; // ascii 120

    // str left
    ASSERT_EQ(std::format("{:6}", c), "x     ");

    // interpret as int -> right
    ASSERT_EQ(std::format("{:6d}", c), "   120");
}

Sign

#include <format>
#include <gtest/gtest.h>

// sign: + for sign on both negative and positive, - for only negative
TEST(format_suite, sign)
{
    ASSERT_EQ(std::format("{:+6}", 42), "   +42");
    ASSERT_EQ(std::format("{:+6}", -42), "   -42");
    ASSERT_EQ(std::format("{:-6}", 42), "    42");
    ASSERT_EQ(std::format("{:-6}", -42), "   -42");
}

Hash: Integral Datatypes

#include <format>
#include <gtest/gtest.h>

TEST(format_suite, hash_integral)
{
    ASSERT_EQ(std::format("{:#x}", 42), "0x2a");
    ASSERT_EQ(std::format("{:#d}", 42), "42"); // default, same as :d
    ASSERT_EQ(std::format("{:#o}", 42), "052");
    ASSERT_EQ(std::format("{:#b}", 42), "0b101010");

    ASSERT_EQ(std::format("{:#6x}", 42), "  0x2a");
    ASSERT_EQ(std::format("{:6d}", 42), "    42");
    ASSERT_EQ(std::format("{:#6b}", 42), "0b101010"); // longer than 6
}

Unicode Support

Not there. See (Incomplete) Unicode in C++.