Make type a scoped enum
This commit is contained in:
parent
b308159be5
commit
74532c23a3
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
54
test/format
54
test/format
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user