Make type a scoped enum

This commit is contained in:
Victor Zverovich 2019-12-21 09:31:14 -08:00
parent b308159be5
commit 74532c23a3
5 changed files with 90 additions and 88 deletions

View File

@ -695,7 +695,7 @@ using has_fallback_formatter =
template <typename Char> struct named_arg_base; template <typename Char> struct named_arg_base;
template <typename T, typename Char> struct named_arg; template <typename T, typename Char> struct named_arg;
enum type { enum class type {
none_type, none_type,
named_arg_type, named_arg_type,
// Integer types should go first, // Integer types should go first,
@ -721,11 +721,11 @@ enum type {
// Maps core type T to the corresponding type enum constant. // Maps core type T to the corresponding type enum constant.
template <typename T, typename Char> template <typename T, typename Char>
struct type_constant : std::integral_constant<type, custom_type> {}; struct type_constant : std::integral_constant<type, type::custom_type> {};
#define FMT_TYPE_CONSTANT(Type, constant) \ #define FMT_TYPE_CONSTANT(Type, constant) \
template <typename Char> \ template <typename Char> \
struct type_constant<Type, Char> : std::integral_constant<type, constant> {} struct type_constant<Type, Char> : std::integral_constant<type, type::constant> {}
FMT_TYPE_CONSTANT(const named_arg_base<Char>&, named_arg_type); FMT_TYPE_CONSTANT(const named_arg_base<Char>&, named_arg_type);
FMT_TYPE_CONSTANT(int, int_type); FMT_TYPE_CONSTANT(int, int_type);
@ -744,13 +744,13 @@ FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type);
FMT_TYPE_CONSTANT(const void*, pointer_type); FMT_TYPE_CONSTANT(const void*, pointer_type);
FMT_CONSTEXPR bool is_integral_type(type t) { FMT_CONSTEXPR bool is_integral_type(type t) {
FMT_ASSERT(t != named_arg_type, "invalid argument type"); FMT_ASSERT(t != type::named_arg_type, "invalid argument type");
return t > none_type && t <= last_integer_type; return t > type::none_type && t <= type::last_integer_type;
} }
FMT_CONSTEXPR bool is_arithmetic_type(type t) { FMT_CONSTEXPR bool is_arithmetic_type(type t) {
FMT_ASSERT(t != named_arg_type, "invalid argument type"); FMT_ASSERT(t != type::named_arg_type, "invalid argument type");
return t > none_type && t <= last_numeric_type; return t > type::none_type && t <= type::last_numeric_type;
} }
template <typename Char> struct string_value { template <typename Char> struct string_value {
@ -1002,10 +1002,10 @@ template <typename Context> class basic_format_arg {
internal::custom_value<Context> custom_; internal::custom_value<Context> custom_;
}; };
FMT_CONSTEXPR basic_format_arg() : type_(internal::none_type) {} FMT_CONSTEXPR basic_format_arg() : type_(internal::type::none_type) {}
FMT_CONSTEXPR explicit operator bool() const FMT_NOEXCEPT { FMT_CONSTEXPR explicit operator bool() const FMT_NOEXCEPT {
return type_ != internal::none_type; return type_ != internal::type::none_type;
} }
internal::type type() const { return type_; } internal::type type() const { return type_; }
@ -1027,47 +1027,47 @@ FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis,
-> decltype(vis(0)) { -> decltype(vis(0)) {
using char_type = typename Context::char_type; using char_type = typename Context::char_type;
switch (arg.type_) { switch (arg.type_) {
case internal::none_type: case internal::type::none_type:
break; break;
case internal::named_arg_type: case internal::type::named_arg_type:
FMT_ASSERT(false, "invalid argument type"); FMT_ASSERT(false, "invalid argument type");
break; break;
case internal::int_type: case internal::type::int_type:
return vis(arg.value_.int_value); return vis(arg.value_.int_value);
case internal::uint_type: case internal::type::uint_type:
return vis(arg.value_.uint_value); return vis(arg.value_.uint_value);
case internal::long_long_type: case internal::type::long_long_type:
return vis(arg.value_.long_long_value); return vis(arg.value_.long_long_value);
case internal::ulong_long_type: case internal::type::ulong_long_type:
return vis(arg.value_.ulong_long_value); return vis(arg.value_.ulong_long_value);
#if FMT_USE_INT128 #if FMT_USE_INT128
case internal::int128_type: case internal::type::int128_type:
return vis(arg.value_.int128_value); return vis(arg.value_.int128_value);
case internal::uint128_type: case internal::type::uint128_type:
return vis(arg.value_.uint128_value); return vis(arg.value_.uint128_value);
#else #else
case internal::int128_type: case internal::type::int128_type:
case internal::uint128_type: case internal::type::uint128_type:
break; break;
#endif #endif
case internal::bool_type: case internal::type::bool_type:
return vis(arg.value_.bool_value); return vis(arg.value_.bool_value);
case internal::char_type: case internal::type::char_type:
return vis(arg.value_.char_value); return vis(arg.value_.char_value);
case internal::float_type: case internal::type::float_type:
return vis(arg.value_.float_value); return vis(arg.value_.float_value);
case internal::double_type: case internal::type::double_type:
return vis(arg.value_.double_value); return vis(arg.value_.double_value);
case internal::long_double_type: case internal::type::long_double_type:
return vis(arg.value_.long_double_value); return vis(arg.value_.long_double_value);
case internal::cstring_type: case internal::type::cstring_type:
return vis(arg.value_.string.data); return vis(arg.value_.string.data);
case internal::string_type: case internal::type::string_type:
return vis(basic_string_view<char_type>(arg.value_.string.data, return vis(basic_string_view<char_type>(arg.value_.string.data,
arg.value_.string.size)); arg.value_.string.size));
case internal::pointer_type: case internal::type::pointer_type:
return vis(arg.value_.pointer); return vis(arg.value_.pointer);
case internal::custom_type: case internal::type::custom_type:
return vis(typename basic_format_arg<Context>::handle(arg.value_.custom)); return vis(typename basic_format_arg<Context>::handle(arg.value_.custom));
} }
return vis(monostate()); return vis(monostate());
@ -1127,7 +1127,7 @@ template <typename> constexpr unsigned long long encode_types() { return 0; }
template <typename Context, typename Arg, typename... Args> template <typename Context, typename Arg, typename... Args>
constexpr unsigned long long encode_types() { constexpr unsigned long long encode_types() {
return mapped_type_constant<Arg, Context>::value | return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) |
(encode_types<Context, Args...>() << packed_arg_bits); (encode_types<Context, Args...>() << packed_arg_bits);
} }
@ -1290,7 +1290,7 @@ template <typename Context> class basic_format_args {
} }
if (index > internal::max_packed_args) return arg; if (index > internal::max_packed_args) return arg;
arg.type_ = type(index); arg.type_ = type(index);
if (arg.type_ == internal::none_type) return arg; if (arg.type_ == internal::type::none_type) return arg;
internal::value<Context>& val = arg.value_; internal::value<Context>& val = arg.value_;
val = values_[index]; val = values_[index];
return arg; return arg;
@ -1323,7 +1323,7 @@ template <typename Context> class basic_format_args {
/** Returns the argument at specified index. */ /** Returns the argument at specified index. */
format_arg get(int index) const { format_arg get(int index) const {
format_arg arg = do_get(index); format_arg arg = do_get(index);
if (arg.type_ == internal::named_arg_type) if (arg.type_ == internal::type::named_arg_type)
arg = arg.value_.named_arg->template deserialize<Context>(); arg = arg.value_.named_arg->template deserialize<Context>();
return arg; return arg;
} }

View File

@ -1330,13 +1330,14 @@ void arg_map<Context>::init(const basic_format_args<Context>& args) {
if (args.is_packed()) { if (args.is_packed()) {
for (int i = 0;; ++i) { for (int i = 0;; ++i) {
internal::type arg_type = args.type(i); internal::type arg_type = args.type(i);
if (arg_type == internal::none_type) return; if (arg_type == internal::type::none_type) return;
if (arg_type == internal::named_arg_type) push_back(args.values_[i]); if (arg_type == internal::type::named_arg_type)
push_back(args.values_[i]);
} }
} }
for (int i = 0, n = args.max_size(); i < n; ++i) { for (int i = 0, n = args.max_size(); i < n; ++i) {
auto type = args.args_[i].type_; auto type = args.args_[i].type_;
if (type == internal::named_arg_type) push_back(args.args_[i].value_); if (type == internal::type::named_arg_type) push_back(args.args_[i].value_);
} }
} }
@ -2047,14 +2048,14 @@ template <typename ErrorHandler> class numeric_specs_checker {
FMT_CONSTEXPR void check_sign() { FMT_CONSTEXPR void check_sign() {
require_numeric_argument(); require_numeric_argument();
if (is_integral_type(arg_type_) && arg_type_ != int_type && if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&
arg_type_ != long_long_type && arg_type_ != internal::char_type) { arg_type_ != type::long_long_type && arg_type_ != type::char_type) {
error_handler_.on_error("format specifier requires signed argument"); error_handler_.on_error("format specifier requires signed argument");
} }
} }
FMT_CONSTEXPR void check_precision() { FMT_CONSTEXPR void check_precision() {
if (is_integral_type(arg_type_) || arg_type_ == internal::pointer_type) if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type)
error_handler_.on_error("precision not allowed for this argument type"); error_handler_.on_error("precision not allowed for this argument type");
} }
@ -2541,7 +2542,7 @@ FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs(
using context = buffer_context<char_type>; using context = buffer_context<char_type>;
using mapped_type = using mapped_type =
conditional_t<internal::mapped_type_constant<T, context>::value != conditional_t<internal::mapped_type_constant<T, context>::value !=
internal::custom_type, type::custom_type,
decltype(arg_mapper<context>().map(std::declval<T>())), T>; decltype(arg_mapper<context>().map(std::declval<T>())), T>;
auto f = conditional_t<has_formatter<mapped_type, context>::value, auto f = conditional_t<has_formatter<mapped_type, context>::value,
formatter<mapped_type, char_type>, formatter<mapped_type, char_type>,
@ -2841,7 +2842,7 @@ class format_int {
template <typename T, typename Char> template <typename T, typename Char>
struct formatter<T, Char, struct formatter<T, Char,
enable_if_t<internal::type_constant<T, Char>::value != enable_if_t<internal::type_constant<T, Char>::value !=
internal::custom_type>> { internal::type::custom_type>> {
FMT_CONSTEXPR formatter() = default; FMT_CONSTEXPR formatter() = default;
// Parses format specifiers stopping either at the end of the range or at the // Parses format specifiers stopping either at the end of the range or at the
@ -2855,40 +2856,40 @@ struct formatter<T, Char,
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler); auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
auto eh = ctx.error_handler(); auto eh = ctx.error_handler();
switch (type) { switch (type) {
case internal::none_type: case internal::type::none_type:
case internal::named_arg_type: case internal::type::named_arg_type:
FMT_ASSERT(false, "invalid argument type"); FMT_ASSERT(false, "invalid argument type");
break; break;
case internal::int_type: case internal::type::int_type:
case internal::uint_type: case internal::type::uint_type:
case internal::long_long_type: case internal::type::long_long_type:
case internal::ulong_long_type: case internal::type::ulong_long_type:
case internal::int128_type: case internal::type::int128_type:
case internal::uint128_type: case internal::type::uint128_type:
case internal::bool_type: case internal::type::bool_type:
handle_int_type_spec(specs_.type, handle_int_type_spec(specs_.type,
internal::int_type_checker<decltype(eh)>(eh)); internal::int_type_checker<decltype(eh)>(eh));
break; break;
case internal::char_type: case internal::type::char_type:
handle_char_specs( handle_char_specs(
&specs_, internal::char_specs_checker<decltype(eh)>(specs_.type, eh)); &specs_, internal::char_specs_checker<decltype(eh)>(specs_.type, eh));
break; break;
case internal::float_type: case internal::type::float_type:
case internal::double_type: case internal::type::double_type:
case internal::long_double_type: case internal::type::long_double_type:
internal::parse_float_type_spec(specs_, eh); internal::parse_float_type_spec(specs_, eh);
break; break;
case internal::cstring_type: case internal::type::cstring_type:
internal::handle_cstring_type_spec( internal::handle_cstring_type_spec(
specs_.type, internal::cstring_type_checker<decltype(eh)>(eh)); specs_.type, internal::cstring_type_checker<decltype(eh)>(eh));
break; break;
case internal::string_type: case internal::type::string_type:
internal::check_string_type_spec(specs_.type, eh); internal::check_string_type_spec(specs_.type, eh);
break; break;
case internal::pointer_type: case internal::type::pointer_type:
internal::check_pointer_type_spec(specs_.type, eh); internal::check_pointer_type_spec(specs_.type, eh);
break; break;
case internal::custom_type: case internal::type::custom_type:
// Custom format specifiers should be checked in parse functions of // Custom format specifiers should be checked in parse functions of
// formatter specializations. // formatter specializations.
break; break;
@ -3024,7 +3025,8 @@ typename basic_format_context<Range, Char>::format_arg
basic_format_context<Range, Char>::arg(basic_string_view<char_type> name) { basic_format_context<Range, Char>::arg(basic_string_view<char_type> name) {
map_.init(args_); map_.init(args_);
format_arg arg = map_.find(name); format_arg arg = map_.find(name);
if (arg.type() == internal::none_type) this->on_error("argument not found"); if (arg.type() == internal::type::none_type)
this->on_error("argument not found");
return arg; return arg;
} }

View File

@ -572,13 +572,13 @@ TEST(CoreTest, ToStringViewForeignStrings) {
fmt::internal::type type = fmt::internal::type type =
fmt::internal::mapped_type_constant<my_string<char>, fmt::internal::mapped_type_constant<my_string<char>,
fmt::format_context>::value; fmt::format_context>::value;
EXPECT_EQ(type, fmt::internal::string_type); EXPECT_EQ(type, fmt::internal::type::string_type);
type = fmt::internal::mapped_type_constant<my_string<wchar_t>, type = fmt::internal::mapped_type_constant<my_string<wchar_t>,
fmt::wformat_context>::value; fmt::wformat_context>::value;
EXPECT_EQ(type, fmt::internal::string_type); EXPECT_EQ(type, fmt::internal::type::string_type);
type = type =
fmt::internal::mapped_type_constant<QString, fmt::wformat_context>::value; fmt::internal::mapped_type_constant<QString, fmt::wformat_context>::value;
EXPECT_EQ(type, fmt::internal::string_type); EXPECT_EQ(type, fmt::internal::type::string_type);
// Does not compile: only wide format contexts are compatible with QString! // Does not compile: only wide format contexts are compatible with QString!
// type = fmt::internal::mapped_type_constant<QString, // type = fmt::internal::mapped_type_constant<QString,
// fmt::format_context>::value; // fmt::format_context>::value;

View File

@ -534,31 +534,31 @@ inline fmt::internal::type get_type(basic_format_arg<Context> arg) {
using char_type = typename Context::char_type; using char_type = typename Context::char_type;
using T = decltype(val); using T = decltype(val);
if (std::is_same_v<T, monostate>) if (std::is_same_v<T, monostate>)
return fmt::internal::none_type; return fmt::internal::type::none_type;
if (std::is_same_v<T, bool>) if (std::is_same_v<T, bool>)
return fmt::internal::bool_type; return fmt::internal::type::bool_type;
if (std::is_same_v<T, char_type>) if (std::is_same_v<T, char_type>)
return fmt::internal::char_type; return fmt::internal::type::char_type;
if (std::is_same_v<T, int>) if (std::is_same_v<T, int>)
return fmt::internal::int_type; return fmt::internal::type::int_type;
if (std::is_same_v<T, unsigned int>) if (std::is_same_v<T, unsigned int>)
return fmt::internal::uint_type; return fmt::internal::type::uint_type;
if (std::is_same_v<T, long long int>) if (std::is_same_v<T, long long int>)
return fmt::internal::long_long_type; return fmt::internal::type::long_long_type;
if (std::is_same_v<T, unsigned long long int>) if (std::is_same_v<T, unsigned long long int>)
return fmt::internal::ulong_long_type; return fmt::internal::type::ulong_long_type;
if (std::is_same_v<T, double>) if (std::is_same_v<T, double>)
return fmt::internal::double_type; return fmt::internal::type::double_type;
if (std::is_same_v<T, long double>) if (std::is_same_v<T, long double>)
return fmt::internal::long_double_type; return fmt::internal::type::long_double_type;
if (std::is_same_v<T, const char_type*>) if (std::is_same_v<T, const char_type*>)
return fmt::internal::cstring_type; return fmt::internal::type::cstring_type;
if (std::is_same_v<T, basic_string_view<char_type>>) if (std::is_same_v<T, basic_string_view<char_type>>)
return fmt::internal::string_type; return fmt::internal::type::string_type;
if (std::is_same_v<T, const void*>) if (std::is_same_v<T, const void*>)
return fmt::internal::pointer_type; return fmt::internal::type::pointer_type;
assert(get_value(arg).index() == 12); assert(get_value(arg).index() == 12);
return fmt::internal::custom_type; return fmt::internal::type::custom_type;
}, arg); }, arg);
} }
@ -649,37 +649,37 @@ struct formatter {
auto type_spec = specs_.type; auto type_spec = specs_.type;
auto eh = ctx.error_handler(); auto eh = ctx.error_handler();
switch (type) { switch (type) {
case internal::none_type: case internal::type::none_type:
case internal::named_arg_type: case internal::type::named_arg_type:
FMT_ASSERT(false, "invalid argument type"); FMT_ASSERT(false, "invalid argument type");
break; break;
case internal::int_type: case internal::type::int_type:
case internal::uint_type: case internal::type::uint_type:
case internal::long_long_type: case internal::type::long_long_type:
case internal::ulong_long_type: case internal::type::ulong_long_type:
case internal::bool_type: case internal::type::bool_type:
handle_int_type_spec(type_spec, handle_int_type_spec(type_spec,
internal::int_type_checker<decltype(eh)>(eh)); internal::int_type_checker<decltype(eh)>(eh));
break; break;
case internal::char_type: case internal::type::char_type:
handle_char_specs( handle_char_specs(
&specs_, internal::char_specs_checker<decltype(eh)>(type_spec, eh)); &specs_, internal::char_specs_checker<decltype(eh)>(type_spec, eh));
break; break;
case internal::double_type: case internal::type::double_type:
case internal::long_double_type: case internal::type::long_double_type:
internal::parse_float_type_spec(specs_, eh); internal::parse_float_type_spec(specs_, eh);
break; break;
case internal::cstring_type: case internal::type::cstring_type:
internal::handle_cstring_type_spec( internal::handle_cstring_type_spec(
type_spec, internal::cstring_type_checker<decltype(eh)>(eh)); type_spec, internal::cstring_type_checker<decltype(eh)>(eh));
break; break;
case internal::string_type: case internal::type::string_type:
internal::check_string_type_spec(type_spec, eh); internal::check_string_type_spec(type_spec, eh);
break; break;
case internal::pointer_type: case internal::type::pointer_type:
internal::check_pointer_type_spec(type_spec, eh); internal::check_pointer_type_spec(type_spec, eh);
break; break;
case internal::custom_type: case internal::type::custom_type:
// Custom format specifiers should be checked in parse functions of // Custom format specifiers should be checked in parse functions of
// formatter specializations. // formatter specializations.
break; break;

View File

@ -2270,7 +2270,7 @@ TEST(FormatTest, ConstexprDynamicSpecsHandler) {
template <size_t N> template <size_t N>
FMT_CONSTEXPR test_format_specs_handler check_specs(const char (&s)[N]) { FMT_CONSTEXPR test_format_specs_handler check_specs(const char (&s)[N]) {
fmt::internal::specs_checker<test_format_specs_handler> checker( fmt::internal::specs_checker<test_format_specs_handler> checker(
test_format_specs_handler(), fmt::internal::double_type); test_format_specs_handler(), fmt::internal::type::double_type);
parse_format_specs(s, s + N, checker); parse_format_specs(s, s + N, checker);
return checker; return checker;
} }