Repository: fmtlib/fmt
File: include/fmt/core.h (C/C++)

Code before:
};

/** An alias to ``basic_format_args<format_context>``. */
// A separate type would result in shorter symbols but break ABI compatibility
// between clang and gcc on ARM (#1919).
using format_args = basic_format_args<format_context>;

// We cannot use enum classes as bit fields because of a gcc bug before 9.3
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 903
namespace align {
enum type { none, left, right, center, numeric };
}
using align_t = align::type;
namespace sign {
enum type { none, minus, plus, space };
}
#else
namespace align {
enum type : unsigned char { none, left, right, center, numeric };
}
using align_t = align::type;
namespace sign {
enum type : unsigned char { none, minus, plus, space };
}
#endif
using sign_t = sign::type;

FMT_BEGIN_DETAIL_NAMESPACE

// Workaround an array initialization issue in gcc 4.8.
template <typename Char> struct fill_t {
 private:
  enum { max_size = 4 };
  Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)};
  unsigned char size_ = 1;

 public:
  FMT_CONSTEXPR void operator=(basic_string_view<Char> s) {
    auto size = s.size();
    if (size > max_size) return throw_format_error("invalid fill");
    for (size_t i = 0; i < size; ++i) data_[i] = s[i];
    size_ = static_cast<unsigned char>(size);
  }

  constexpr auto size() const -> size_t { return size_; }
  constexpr auto data() const -> const Char* { return data_; }

  FMT_CONSTEXPR auto operator[](size_t index) -> Char& { return data_[index]; }
  FMT_CONSTEXPR auto operator[](size_t index) const -> const Char& {
    return data_[index];

Review comment (refactor):
Maybe simplify:
```c++
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 903
# define FMT_ENUM_UNDERLYING_TYPE(type)
#else
# define FMT_ENUM_UNDERLYING_TYPE(type) : type
#endif


namespace align {
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char) { none, left, right, center, numeric };
}
using align_t = align::type;
namespace sign {
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char) { none, minus, plus, space };
}
```

?

Code after:
};

/** An alias to ``basic_format_args<format_context>``. */
// A separate type would result in shorter symbols but break ABI compatibility
// between clang and gcc on ARM (#1919).
using format_args = basic_format_args<format_context>;

// We cannot use enum classes as bit fields because of a gcc bug,
// so we put them in namespaces instead.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
// Additionally, if an underlying type is specified, older gcc incorrectly warns
// that the type is too small for all the enum values.
// Both these bugs are fixed as of gcc 9.3.
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 903
# define FMT_ENUM_UNDERLYING_TYPE(type)
#else
# define FMT_ENUM_UNDERLYING_TYPE(type) : type
#endif
namespace align {
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char) { none, left, right, center, numeric };
}
using align_t = align::type;
namespace sign {
enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char) { none, minus, plus, space };
}
using sign_t = sign::type;

FMT_BEGIN_DETAIL_NAMESPACE

// Workaround an array initialization issue in gcc 4.8.
template <typename Char> struct fill_t {
 private:
  enum { max_size = 4 };
  Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)};
  unsigned char size_ = 1;

 public:
  FMT_CONSTEXPR void operator=(basic_string_view<Char> s) {
    auto size = s.size();
    if (size > max_size) return throw_format_error("invalid fill");
    for (size_t i = 0; i < size; ++i) data_[i] = s[i];
    size_ = static_cast<unsigned char>(size);
  }

  constexpr auto size() const -> size_t { return size_; }
  constexpr auto data() const -> const Char* { return data_; }

  FMT_CONSTEXPR auto operator[](size_t index) -> Char& { return data_[index]; }
  FMT_CONSTEXPR auto operator[](size_t index) const -> const Char& {
    return data_[index];
  }