Commit a03842b0 authored by Victor Zverovich's avatar Victor Zverovich

More compile-time checks

parent 1c855a47
...@@ -3812,33 +3812,37 @@ struct udl_format_handler { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) { ...@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment