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

View File

@ -1330,13 +1330,14 @@ void arg_map<Context>::init(const basic_format_args<Context>& args) {
if (args.is_packed()) {
for (int i = 0;; ++i) {
internal::type arg_type = args.type(i);
if (arg_type == internal::none_type) return;
if (arg_type == internal::named_arg_type) push_back(args.values_[i]);
if (arg_type == internal::type::none_type) return;
if (arg_type == internal::type::named_arg_type)
push_back(args.values_[i]);
}
}
for (int i = 0, n = args.max_size(); i < n; ++i) {
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() {
require_numeric_argument();
if (is_integral_type(arg_type_) && arg_type_ != int_type &&
arg_type_ != long_long_type && arg_type_ != internal::char_type) {
if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&
arg_type_ != type::long_long_type && arg_type_ != type::char_type) {
error_handler_.on_error("format specifier requires signed argument");
}
}
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");
}
@ -2541,7 +2542,7 @@ FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs(
using context = buffer_context<char_type>;
using mapped_type =
conditional_t<internal::mapped_type_constant<T, context>::value !=
internal::custom_type,
type::custom_type,
decltype(arg_mapper<context>().map(std::declval<T>())), T>;
auto f = conditional_t<has_formatter<mapped_type, context>::value,
formatter<mapped_type, char_type>,
@ -2841,7 +2842,7 @@ class format_int {
template <typename T, typename Char>
struct formatter<T, Char,
enable_if_t<internal::type_constant<T, Char>::value !=
internal::custom_type>> {
internal::type::custom_type>> {
FMT_CONSTEXPR formatter() = default;
// 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 eh = ctx.error_handler();
switch (type) {
case internal::none_type:
case internal::named_arg_type:
case internal::type::none_type:
case internal::type::named_arg_type:
FMT_ASSERT(false, "invalid argument type");
break;
case internal::int_type:
case internal::uint_type:
case internal::long_long_type:
case internal::ulong_long_type:
case internal::int128_type:
case internal::uint128_type:
case internal::bool_type:
case internal::type::int_type:
case internal::type::uint_type:
case internal::type::long_long_type:
case internal::type::ulong_long_type:
case internal::type::int128_type:
case internal::type::uint128_type:
case internal::type::bool_type:
handle_int_type_spec(specs_.type,
internal::int_type_checker<decltype(eh)>(eh));
break;
case internal::char_type:
case internal::type::char_type:
handle_char_specs(
&specs_, internal::char_specs_checker<decltype(eh)>(specs_.type, eh));
break;
case internal::float_type:
case internal::double_type:
case internal::long_double_type:
case internal::type::float_type:
case internal::type::double_type:
case internal::type::long_double_type:
internal::parse_float_type_spec(specs_, eh);
break;
case internal::cstring_type:
case internal::type::cstring_type:
internal::handle_cstring_type_spec(
specs_.type, internal::cstring_type_checker<decltype(eh)>(eh));
break;
case internal::string_type:
case internal::type::string_type:
internal::check_string_type_spec(specs_.type, eh);
break;
case internal::pointer_type:
case internal::type::pointer_type:
internal::check_pointer_type_spec(specs_.type, eh);
break;
case internal::custom_type:
case internal::type::custom_type:
// Custom format specifiers should be checked in parse functions of
// formatter specializations.
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) {
map_.init(args_);
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;
}

View File

@ -572,13 +572,13 @@ TEST(CoreTest, ToStringViewForeignStrings) {
fmt::internal::type type =
fmt::internal::mapped_type_constant<my_string<char>,
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>,
fmt::wformat_context>::value;
EXPECT_EQ(type, fmt::internal::string_type);
EXPECT_EQ(type, fmt::internal::type::string_type);
type =
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!
// type = fmt::internal::mapped_type_constant<QString,
// 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 T = decltype(val);
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>)
return fmt::internal::bool_type;
return fmt::internal::type::bool_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>)
return fmt::internal::int_type;
return fmt::internal::type::int_type;
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>)
return fmt::internal::long_long_type;
return fmt::internal::type::long_long_type;
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>)
return fmt::internal::double_type;
return fmt::internal::type::double_type;
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*>)
return fmt::internal::cstring_type;
return fmt::internal::type::cstring_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*>)
return fmt::internal::pointer_type;
return fmt::internal::type::pointer_type;
assert(get_value(arg).index() == 12);
return fmt::internal::custom_type;
return fmt::internal::type::custom_type;
}, arg);
}
@ -649,37 +649,37 @@ struct formatter {
auto type_spec = specs_.type;
auto eh = ctx.error_handler();
switch (type) {
case internal::none_type:
case internal::named_arg_type:
case internal::type::none_type:
case internal::type::named_arg_type:
FMT_ASSERT(false, "invalid argument type");
break;
case internal::int_type:
case internal::uint_type:
case internal::long_long_type:
case internal::ulong_long_type:
case internal::bool_type:
case internal::type::int_type:
case internal::type::uint_type:
case internal::type::long_long_type:
case internal::type::ulong_long_type:
case internal::type::bool_type:
handle_int_type_spec(type_spec,
internal::int_type_checker<decltype(eh)>(eh));
break;
case internal::char_type:
case internal::type::char_type:
handle_char_specs(
&specs_, internal::char_specs_checker<decltype(eh)>(type_spec, eh));
break;
case internal::double_type:
case internal::long_double_type:
case internal::type::double_type:
case internal::type::long_double_type:
internal::parse_float_type_spec(specs_, eh);
break;
case internal::cstring_type:
case internal::type::cstring_type:
internal::handle_cstring_type_spec(
type_spec, internal::cstring_type_checker<decltype(eh)>(eh));
break;
case internal::string_type:
case internal::type::string_type:
internal::check_string_type_spec(type_spec, eh);
break;
case internal::pointer_type:
case internal::type::pointer_type:
internal::check_pointer_type_spec(type_spec, eh);
break;
case internal::custom_type:
case internal::type::custom_type:
// Custom format specifiers should be checked in parse functions of
// formatter specializations.
break;

View File

@ -2270,7 +2270,7 @@ TEST(FormatTest, ConstexprDynamicSpecsHandler) {
template <size_t N>
FMT_CONSTEXPR test_format_specs_handler check_specs(const char (&s)[N]) {
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);
return checker;
}