0

So I have the following struct:

struct Snowflake {
    Snowflake() : _value(0) {}
    Snowflake(uint64_t value) : _value(value) {}
    Snowflake(std::string value) : _value(std::stoull(value)) {}
    Snowflake(const Snowflake &) = default;

    operator uint64_t &() { return _value; }

    operator uint64_t() const { return _value; }

    operator std::string() const { return std::to_string(_value); }

    Snowflake &operator=(uint64_t val) {
        _value = val;
        return *this;
    }

    Snowflake &operator=(const std::string &str) {
        _value = std::stoull(str);
        return *this;
    }

    Snowflake &operator=(const Snowflake &s) {
        _value = s._value;
        return *this;
    }

  protected:
    uint64_t _value;
};

If I declare Snowflake snowflake = 336227221100429313; then I can use fmt::print("Snowflake: {}", snowflake); for example just fine but I can't use std::vector<Snowflake> snowflakes{164234463247597568, 106615803402547200, 268487751370801152}; with fmt::print("Snowflakes: {}", snowflakes); I get the following error:

In file included from -snip-/cmake-build-debug/_deps/fmt-src/include/fmt/format.h:48,
                 from -snip-/snowflake.hh:8,
                 from -snip-/main.cpp:2:
-snip-/cmake-build-debug/_deps/fmt-src/include/fmt/core.h: In instantiation of ‘constexpr fmt::v8::detail::value<Context> fmt::v8::detail::make_arg(T&&) [with bool IS_PACKED = true; Context = fmt::v8::basic_format_context<fmt::v8::appender, char>; fmt::v8::detail::type <anonymous> = fmt::v8::detail::type::custom_type; T = std::vector<Snowflake>&; typename std::enable_if<IS_PACKED, int>::type <anonymous> = 0]’:
-snip-/cmake-build-debug/_deps/fmt-src/include/fmt/core.h:1807:77:   required from ‘constexpr fmt::v8::format_arg_store<Context, Args>::format_arg_store(T&& ...) [with T = {std::vector<Snowflake, std::allocator<Snowflake> >&}; Context = fmt::v8::basic_format_context<fmt::v8::appender, char>; Args = {std::vector<Snowflake, std::allocator<Snowflake> >}]’
-snip-/cmake-build-debug/_deps/fmt-src/include/fmt/core.h:1824:38:   required from ‘constexpr fmt::v8::format_arg_store<Context, fmt::v8::remove_cvref_t<Args>...> fmt::v8::make_format_args(Args&& ...) [with Context = fmt::v8::basic_format_context<fmt::v8::appender, char>; Args = {std::vector<Snowflake, std::allocator<Snowflake> >&}]’
-snip-/cmake-build-debug/_deps/fmt-src/include/fmt/core.h:3156:44:   required from ‘void fmt::v8::print(fmt::v8::format_string<T ...>, T&& ...) [with T = {std::vector<Snowflake, std::allocator<Snowflake> >&}; fmt::v8::format_string<T ...> = fmt::v8::basic_format_string<char, std::vector<Snowflake, std::allocator<Snowflake> >&>]’
-snip-/main.cpp:10:44:   required from here
-snip-/cmake-build-debug/_deps/fmt-src/include/fmt/core.h:1680:7: error: static assertion failed: Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#udt
 1680 |       formattable,
      |       ^~~~~~~~~~~

I tried declaring the following:

template <> struct fmt::formatter<Snowflake> : formatter<uint64_t> {
    template <typename FormatContext>
    auto format(Snowflake s, FormatContext &ctx) {
        return formatter<uint64_t>::format(s, ctx);
    }
};

but that hasn't solved the issue. Do I need to celare a fmt::formatter for std::vector<Snowflake>? What would be the easiest way to do that?

Aido
  • 1,524
  • 3
  • 18
  • 41
  • I don't recall `std::vector` being formattable at all. There's `fmt::join` you could use for formatting ranges. – ALX23z Nov 13 '21 at 16:07

1 Answers1

1

It works in the current version of {fmt} (https://godbolt.org/z/98qzcb8r9):

#include <fmt/ranges.h>

...

auto snowflake = Snowflake(336227221100429313);
fmt::print("Snowflake: {}\n", snowflake);
auto snowflakes = std::vector<Snowflake>{164234463247597568, 106615803402547200, 268487751370801152};
fmt::print("{}\n", snowflakes);

prints

Snowflake: 336227221100429313
[164234463247597568, 106615803402547200, 268487751370801152]

Relying on implicit conversion is not recommended though.

vitaut
  • 49,672
  • 25
  • 199
  • 336