Search code examples
c++c++20fmt

Filling after quoted value in fmt


I want to fill after a quoted value with C++ fmt. I know I can just make the quoting in one step and then just use fmt with one argument, but I presume that is slower and from readability perspective I would like to do it in one go. I have this solution.

but is seems a bit clunky, I am manually doing alignment computations accounting for the fact I have quotes around the value...

#include <array>
#include <string>
#include <iostream>
#include <fmt/format.h>



void write_padded(const int i,char* data) {
    // note: - format_to_n will not zero termiante if out of space
    //       - use '^' as a fill char for visibility
    auto result = fmt::format_to_n(data,7, R"("{}{:^<5})",i,'\"');
    *result.out = '\0';
}


int main() {
    // space for 5 digits, 2 quotes \0
    std::array<char, 8> data{};
    write_padded(1, data.data());
    std::cout << data.data() << std::endl;
    write_padded(10, data.data());
    std::cout << data.data() << std::endl;
    write_padded(123456789, data.data());
    std::cout << data.data() << std::endl;
    write_padded(54321, data.data());
    std::cout << data.data() << std::endl;    
}

This seems to work, but I would like to do this without me doing manual computation of width . and maybe also with a bit nicer format string.

note: I know integers can be longer than 5 digits and that magic numbers are bad, but even with named variables I would still need to do computations.


Solution

  • You can write a formatter that does quoting, for example:

    #include <fmt/format.h>
    
    struct quoted {
      int value;
    };
    
    template <>
    struct fmt::formatter<quoted> : formatter<string_view> {
      auto format(quoted q, format_context& ctx) const {
        auto buf = fmt::memory_buffer();
        fmt::format_to(std::back_inserter(buf), "\"{}\"", q.value);
        return formatter<string_view>::format({buf.data(), buf.size()}, ctx);
      }
    };
    
    int main() {
      fmt::print("{:^<7}\n", quoted{1});
    }
    

    This prints

    "1"^^^^
    

    https://godbolt.org/z/Gs5qPTT13