mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-15 07:20:05 +00:00
Make format_specs construction constexpr
This commit is contained in:
parent
a38bd9ca24
commit
6b3840b73c
@ -1630,12 +1630,13 @@ struct align_spec : empty_spec {
|
||||
wchar_t fill_;
|
||||
alignment align_;
|
||||
|
||||
align_spec(unsigned width, wchar_t fill, alignment align = ALIGN_DEFAULT)
|
||||
constexpr align_spec(
|
||||
unsigned width, wchar_t fill, alignment align = ALIGN_DEFAULT)
|
||||
: width_(width), fill_(fill), align_(align) {}
|
||||
|
||||
unsigned width() const { return width_; }
|
||||
wchar_t fill() const { return fill_; }
|
||||
alignment align() const { return align_; }
|
||||
constexpr unsigned width() const { return width_; }
|
||||
constexpr wchar_t fill() const { return fill_; }
|
||||
constexpr alignment align() const { return align_; }
|
||||
|
||||
int precision() const { return -1; }
|
||||
};
|
||||
@ -1670,7 +1671,8 @@ class basic_format_specs : public align_spec {
|
||||
int precision_;
|
||||
Char type_;
|
||||
|
||||
basic_format_specs(unsigned width = 0, char type = 0, wchar_t fill = ' ')
|
||||
constexpr basic_format_specs(
|
||||
unsigned width = 0, char type = 0, wchar_t fill = ' ')
|
||||
: align_spec(width, fill), flags_(0), precision_(-1), type_(type) {}
|
||||
|
||||
template <typename... FormatSpecs>
|
||||
@ -1679,9 +1681,9 @@ class basic_format_specs : public align_spec {
|
||||
set(specs...);
|
||||
}
|
||||
|
||||
bool flag(unsigned f) const { return (flags_ & f) != 0; }
|
||||
int precision() const { return precision_; }
|
||||
Char type() const { return type_; }
|
||||
constexpr bool flag(unsigned f) const { return (flags_ & f) != 0; }
|
||||
constexpr int precision() const { return precision_; }
|
||||
constexpr Char type() const { return type_; }
|
||||
};
|
||||
|
||||
typedef basic_format_specs<char> format_specs;
|
||||
@ -3114,29 +3116,30 @@ struct error_handler {
|
||||
template <typename Char>
|
||||
class specs_setter : public error_handler {
|
||||
public:
|
||||
explicit specs_setter(basic_format_specs<Char> &specs): specs_(specs) {}
|
||||
explicit constexpr specs_setter(basic_format_specs<Char> &specs):
|
||||
specs_(specs) {}
|
||||
|
||||
void on_align(alignment align) { specs_.align_ = align; }
|
||||
void on_fill(Char fill) { specs_.fill_ = fill; }
|
||||
void on_plus() { specs_.flags_ |= SIGN_FLAG | PLUS_FLAG; }
|
||||
void on_minus() { specs_.flags_ |= MINUS_FLAG; }
|
||||
void on_space() { specs_.flags_ |= SIGN_FLAG; }
|
||||
void on_hash() { specs_.flags_ |= HASH_FLAG; }
|
||||
constexpr void on_align(alignment align) { specs_.align_ = align; }
|
||||
constexpr void on_fill(Char fill) { specs_.fill_ = fill; }
|
||||
constexpr void on_plus() { specs_.flags_ |= SIGN_FLAG | PLUS_FLAG; }
|
||||
constexpr void on_minus() { specs_.flags_ |= MINUS_FLAG; }
|
||||
constexpr void on_space() { specs_.flags_ |= SIGN_FLAG; }
|
||||
constexpr void on_hash() { specs_.flags_ |= HASH_FLAG; }
|
||||
|
||||
void on_zero() {
|
||||
constexpr void on_zero() {
|
||||
specs_.align_ = ALIGN_NUMERIC;
|
||||
specs_.fill_ = '0';
|
||||
}
|
||||
|
||||
void on_width(unsigned width) { specs_.width_ = width; }
|
||||
void on_precision(unsigned precision) { specs_.precision_ = precision; }
|
||||
void end_precision() {}
|
||||
constexpr void on_width(unsigned width) { specs_.width_ = width; }
|
||||
constexpr void on_precision(unsigned precision) {
|
||||
specs_.precision_ = precision;
|
||||
}
|
||||
constexpr void end_precision() {}
|
||||
|
||||
void on_type(Char type) { specs_.type_ = type; }
|
||||
constexpr void on_type(Char type) { specs_.type_ = type; }
|
||||
|
||||
protected:
|
||||
~specs_setter() {}
|
||||
|
||||
basic_format_specs<Char> &specs_;
|
||||
};
|
||||
|
||||
@ -3229,7 +3232,7 @@ class specs_handler: public specs_setter<typename Context::char_type> {
|
||||
public:
|
||||
typedef typename Context::char_type char_type;
|
||||
|
||||
specs_handler(basic_format_specs<char_type> &specs, Context &ctx)
|
||||
constexpr specs_handler(basic_format_specs<char_type> &specs, Context &ctx)
|
||||
: specs_setter<char_type>(specs), context_(ctx) {}
|
||||
|
||||
template <typename Id>
|
||||
@ -3508,8 +3511,11 @@ const Char *do_format_arg(basic_buffer<Char> &buffer,
|
||||
basic_format_specs<Char> specs;
|
||||
if (*it == ':') {
|
||||
ctx.advance_to(pointer_from(++it));
|
||||
if (visit(custom_formatter<Char, Context>(buffer, ctx), arg))
|
||||
if (visit(custom_formatter<Char, Context>(buffer, ctx), arg)) {
|
||||
// TODO: if constexpr, then use formatter<T>::parse, else dispatch
|
||||
// dynamically
|
||||
return ctx.begin();
|
||||
}
|
||||
specs_checker<specs_handler<Context>>
|
||||
handler(specs_handler<Context>(specs, ctx), arg.type());
|
||||
it = parse_format_specs(it, handler);
|
||||
|
@ -1619,7 +1619,7 @@ TEST(FormatTest, ConstexprParseArgID) {
|
||||
static_assert(parse_arg_id("!").res == test_arg_id_handler::ERROR, "");
|
||||
}
|
||||
|
||||
struct test_format_specs_handlers {
|
||||
struct test_format_specs_handler {
|
||||
enum Result { NONE, PLUS, MINUS, SPACE, HASH, ZERO, ERROR };
|
||||
Result res = NONE;
|
||||
|
||||
@ -1656,24 +1656,62 @@ struct test_format_specs_handlers {
|
||||
constexpr void on_error(const char *) { res = ERROR; }
|
||||
};
|
||||
|
||||
constexpr test_format_specs_handlers parse_specs(const char *s) {
|
||||
test_format_specs_handlers h;
|
||||
constexpr test_format_specs_handler parse_test_specs(const char *s) {
|
||||
test_format_specs_handler h;
|
||||
fmt::internal::parse_format_specs(s, h);
|
||||
return h;
|
||||
}
|
||||
|
||||
TEST(FormatTest, ConstexprParseFormatSpecs) {
|
||||
static_assert(parse_specs("<").align == fmt::ALIGN_LEFT, "");
|
||||
static_assert(parse_specs("*^").fill == '*', "");
|
||||
static_assert(parse_specs("+").res == test_format_specs_handlers::PLUS, "");
|
||||
static_assert(parse_specs("-").res == test_format_specs_handlers::MINUS, "");
|
||||
static_assert(parse_specs(" ").res == test_format_specs_handlers::SPACE, "");
|
||||
static_assert(parse_specs("#").res == test_format_specs_handlers::HASH, "");
|
||||
static_assert(parse_specs("0").res == test_format_specs_handlers::ZERO, "");
|
||||
static_assert(parse_specs("42").width == 42, "");
|
||||
static_assert(parse_specs("{42}").width_ref.index == 42, "");
|
||||
static_assert(parse_specs(".42").precision == 42, "");
|
||||
static_assert(parse_specs(".{42}").precision_ref.index == 42, "");
|
||||
static_assert(parse_specs("d").type == 'd', "");
|
||||
static_assert(parse_specs("{<").res == test_format_specs_handlers::ERROR, "");
|
||||
using handler = test_format_specs_handler;
|
||||
static_assert(parse_test_specs("<").align == fmt::ALIGN_LEFT, "");
|
||||
static_assert(parse_test_specs("*^").fill == '*', "");
|
||||
static_assert(parse_test_specs("+").res == handler::PLUS, "");
|
||||
static_assert(parse_test_specs("-").res == handler::MINUS, "");
|
||||
static_assert(parse_test_specs(" ").res == handler::SPACE, "");
|
||||
static_assert(parse_test_specs("#").res == handler::HASH, "");
|
||||
static_assert(parse_test_specs("0").res == handler::ZERO, "");
|
||||
static_assert(parse_test_specs("42").width == 42, "");
|
||||
static_assert(parse_test_specs("{42}").width_ref.index == 42, "");
|
||||
static_assert(parse_test_specs(".42").precision == 42, "");
|
||||
static_assert(parse_test_specs(".{42}").precision_ref.index == 42, "");
|
||||
static_assert(parse_test_specs("d").type == 'd', "");
|
||||
static_assert(parse_test_specs("{<").res == handler::ERROR, "");
|
||||
}
|
||||
|
||||
struct test_context {
|
||||
using char_type = char;
|
||||
|
||||
fmt::basic_arg<test_context> next_arg() {
|
||||
return fmt::basic_arg<test_context>();
|
||||
}
|
||||
|
||||
template <typename Id>
|
||||
fmt::basic_arg<test_context> get_arg(Id) {
|
||||
return fmt::basic_arg<test_context>();
|
||||
}
|
||||
|
||||
template <typename Id>
|
||||
void check_arg_id(Id) {}
|
||||
};
|
||||
|
||||
constexpr fmt::format_specs parse_specs(const char *s) {
|
||||
fmt::format_specs specs;
|
||||
test_context ctx;
|
||||
fmt::internal::specs_handler<test_context> h(specs, ctx);
|
||||
parse_format_specs(s, h);
|
||||
return specs;
|
||||
}
|
||||
|
||||
TEST(FormatTest, ConstexprSpecsHandler) {
|
||||
static_assert(parse_specs("<").align() == fmt::ALIGN_LEFT, "");
|
||||
static_assert(parse_specs("*^").fill() == '*', "");
|
||||
static_assert(parse_specs("+").flag(fmt::PLUS_FLAG), "");
|
||||
static_assert(parse_specs("-").flag(fmt::MINUS_FLAG), "");
|
||||
static_assert(parse_specs(" ").flag(fmt::SIGN_FLAG), "");
|
||||
static_assert(parse_specs("#").flag(fmt::HASH_FLAG), "");
|
||||
static_assert(parse_specs("0").align() == fmt::ALIGN_NUMERIC, "");
|
||||
static_assert(parse_specs("42").width() == 42, "");
|
||||
static_assert(parse_specs(".42").precision() == 42, "");
|
||||
static_assert(parse_specs("d").type() == 'd', "");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user