mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 10:47:35 +02:00
More compile-time checks
This commit is contained in:
@ -3812,33 +3812,37 @@ struct udl_format_handler {
|
|||||||
|
|
||||||
constexpr void on_text(const Char *, const Char *) {}
|
constexpr void on_text(const Char *, const Char *) {}
|
||||||
|
|
||||||
constexpr void on_arg_id() { ++arg_index_; }
|
constexpr void on_arg_id() {
|
||||||
|
++arg_index_;
|
||||||
template <typename T>
|
check_arg_index();
|
||||||
constexpr void on_arg_id(T) {}
|
}
|
||||||
|
constexpr void on_arg_id(unsigned index) {
|
||||||
|
arg_index_ = index;
|
||||||
|
check_arg_index();
|
||||||
|
}
|
||||||
|
constexpr void on_arg_id(basic_string_view<Char>) {}
|
||||||
|
|
||||||
constexpr void on_replacement_field(const Char *) {}
|
constexpr void on_replacement_field(const Char *) {}
|
||||||
|
|
||||||
constexpr const Char *on_format_specs(const Char *s) {
|
constexpr const Char *on_format_specs(const Char *s) {
|
||||||
if (arg_index_ < 0 || arg_index_ >= sizeof...(Args)) {
|
|
||||||
on_error("argument index out of range");
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
parse_context<Char> ctx(basic_string_view<Char>(s, end_ - s));
|
parse_context<Char> ctx(basic_string_view<Char>(s, end_ - s));
|
||||||
return parse_funcs_[arg_index_](ctx);
|
return parse_funcs_[arg_index_](ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void on_error(const char *) { error_ = true; }
|
// This function is intentionally not constexpr to give a compile-time error.
|
||||||
|
void on_error(const char *);
|
||||||
constexpr bool is_valid() const { return !error_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
constexpr void check_arg_index() {
|
||||||
|
if (arg_index_ < 0 || arg_index_ >= sizeof...(Args))
|
||||||
|
on_error("argument index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
// Format specifier parsing function.
|
// Format specifier parsing function.
|
||||||
using parse_func = const Char *(*)(parse_context<Char> &);
|
using parse_func = const Char *(*)(parse_context<Char> &);
|
||||||
|
|
||||||
const Char *end_;
|
const Char *end_;
|
||||||
int arg_index_ = -1;
|
int arg_index_ = -1;
|
||||||
bool error_ = false;
|
|
||||||
parse_func parse_funcs_[sizeof...(Args)] = {
|
parse_func parse_funcs_[sizeof...(Args)] = {
|
||||||
&parse_format_specs<Char, Args>...
|
&parse_format_specs<Char, Args>...
|
||||||
};
|
};
|
||||||
@ -3850,7 +3854,7 @@ class udl_formatter {
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
std::basic_string<Char> operator()(const Args &... args) const {
|
std::basic_string<Char> operator()(const Args &... args) const {
|
||||||
constexpr Char s[] = {CHARS..., '\0'};
|
constexpr Char s[] = {CHARS..., '\0'};
|
||||||
static_assert(check_format<Args...>(s), "error parsing format string");
|
constexpr bool invalid_format = check_format<Args...>(s);
|
||||||
return format(s, args...);
|
return format(s, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3859,7 +3863,7 @@ class udl_formatter {
|
|||||||
static constexpr bool check_format(const Char *s) {
|
static constexpr bool check_format(const Char *s) {
|
||||||
udl_format_handler<Char, Args...> handler(s + sizeof...(CHARS));
|
udl_format_handler<Char, Args...> handler(s + sizeof...(CHARS));
|
||||||
internal::parse_format_string(s, handler);
|
internal::parse_format_string(s, handler);
|
||||||
return handler.is_valid();
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
# else
|
# else
|
||||||
|
@ -1234,8 +1234,11 @@ namespace fmt {
|
|||||||
template <>
|
template <>
|
||||||
struct formatter<Date> {
|
struct formatter<Date> {
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
|
constexpr auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
|
||||||
return ctx.begin();
|
auto it = ctx.begin();
|
||||||
|
if (*it == 'd')
|
||||||
|
++it;
|
||||||
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
void format(buffer &buf, const Date &d, context &) {
|
void format(buffer &buf, const Date &d, context &) {
|
||||||
@ -1813,8 +1816,7 @@ TEST(FormatTest, ConstexprParseFormatString) {
|
|||||||
static_assert(parse_string("{:}"), "");
|
static_assert(parse_string("{:}"), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FMT_UDL_TEMPLATE
|
|
||||||
TEST(FormatTest, UdlTemplate) {
|
TEST(FormatTest, UdlTemplate) {
|
||||||
EXPECT_EQ("foo", "foo"_format());
|
EXPECT_EQ("foo", "foo"_format());
|
||||||
|
EXPECT_EQ(" 42", "{0:10}"_format(42));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
Reference in New Issue
Block a user