Repository: fmtlib/fmt
File: test/std-test.cc (C++)

Code before:
            "[optional(1), optional(2), optional(3)]");
  EXPECT_EQ(
      fmt::format("{}", std::optional<std::optional<const char*>>{{"nested"}}),
      "optional(optional(\"nested\"))");
  EXPECT_EQ(
      fmt::format("{:<{}}", std::optional{std::string{"left aligned"}}, 30),
      "optional(\"left aligned\"                )");
  EXPECT_EQ(
      fmt::format("{::d}", std::optional{std::vector{'h', 'e', 'l', 'l', 'o'}}),
      "optional([104, 101, 108, 108, 111])");
  EXPECT_EQ(fmt::format("{}", std::optional{std::string{"string"}}),
            "optional(\"string\")");
  EXPECT_EQ(fmt::format("{}", std::optional{'C'}), "optional(\'C\')");
  EXPECT_EQ(fmt::format("{:.{}f}", std::optional{3.14}, 1), "optional(3.1)");

  struct unformattable {};
  EXPECT_FALSE((fmt::is_formattable<unformattable>::value));
  EXPECT_FALSE((fmt::is_formattable<std::optional<unformattable>>::value));
  EXPECT_TRUE((fmt::is_formattable<std::optional<int>>::value));
#endif
}

// this struct exists only to force a variant to be
// valueless by exception
// NOLINTNEXTLINE
struct throws_on_move_t {
  throws_on_move_t() = default;

  // NOLINTNEXTLINE
  [[noreturn]] throws_on_move_t(throws_on_move_t&&) {
    throw std::runtime_error{"Thrown by throws_on_move_t"};
  }

  throws_on_move_t(const throws_on_move_t&) = default;
};

template <> struct fmt::formatter<throws_on_move_t> : formatter<string_view> {
  template <typename FormatContext>
  auto format(const throws_on_move_t&, FormatContext& ctx) const {
    string_view str{"<throws_on_move_t>"};
    return formatter<string_view>::format(str, ctx);
  }
};

TEST(std_test, variant) {
#ifdef __cpp_lib_variant
  EXPECT_EQ(fmt::format("{}", std::monostate{}), "monostate");
  using V0 = std::variant<int, float, std::string, char>;
  V0 v0(42);
  V0 v1(1.5f);
  V0 v2("hello");

Review comment (suggestion):
`_t` suffix is normally used for aliases (typedefs), please remove.

Code after:
            "[optional(1), optional(2), optional(3)]");
  EXPECT_EQ(
      fmt::format("{}", std::optional<std::optional<const char*>>{{"nested"}}),
      "optional(optional(\"nested\"))");
  EXPECT_EQ(
      fmt::format("{:<{}}", std::optional{std::string{"left aligned"}}, 30),
      "optional(\"left aligned\"                )");
  EXPECT_EQ(
      fmt::format("{::d}", std::optional{std::vector{'h', 'e', 'l', 'l', 'o'}}),
      "optional([104, 101, 108, 108, 111])");
  EXPECT_EQ(fmt::format("{}", std::optional{std::string{"string"}}),
            "optional(\"string\")");
  EXPECT_EQ(fmt::format("{}", std::optional{'C'}), "optional(\'C\')");
  EXPECT_EQ(fmt::format("{:.{}f}", std::optional{3.14}, 1), "optional(3.1)");

  struct unformattable {};
  EXPECT_FALSE((fmt::is_formattable<unformattable>::value));
  EXPECT_FALSE((fmt::is_formattable<std::optional<unformattable>>::value));
  EXPECT_TRUE((fmt::is_formattable<std::optional<int>>::value));
#endif
}

struct throws_on_move {
  throws_on_move() = default;

  [[noreturn]] throws_on_move(throws_on_move&&) {
    throw std::runtime_error("Thrown by throws_on_move");
  }

  throws_on_move(const throws_on_move&) = default;
};

namespace fmt {
template <> struct formatter<throws_on_move> : formatter<string_view> {
  auto format(const throws_on_move&, format_context& ctx) const
      -> decltype(ctx.out()) {
    string_view str("<throws_on_move>");
    return formatter<string_view>::format(str, ctx);
  }
};
}  // namespace fmt

TEST(std_test, variant) {
#ifdef __cpp_lib_variant
  EXPECT_EQ(fmt::format("{}", std::monostate{}), "monostate");
  using V0 = std::variant<int, float, std::string, char>;
  V0 v0(42);
  V0 v1(1.5f);
  V0 v2("hello");
  V0 v3('i');
  EXPECT_EQ(fmt::format("{}", v0), "variant(42)");