mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-15 07:20:05 +00:00
Relax constexpr requirements
This commit is contained in:
parent
dc5403612e
commit
1f57243b49
@ -42,12 +42,18 @@
|
||||
# define FMT_MSC_VER 0
|
||||
#endif
|
||||
|
||||
#ifndef FMT_CONSTEXPR
|
||||
# if FMT_HAS_FEATURE(cxx_constexpr)
|
||||
# define FMT_CONSTEXPR constexpr
|
||||
# else
|
||||
# define FMT_CONSTEXPR
|
||||
# endif
|
||||
// Check if relaxed c++14 constexpr is supported.
|
||||
#ifndef FMT_USE_CONSTEXPR
|
||||
# define FMT_USE_CONSTEXPR \
|
||||
(FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_GCC_VERSION >= 500 || \
|
||||
FMT_MSC_VER >= 1910)
|
||||
#endif
|
||||
#if FMT_USE_CONSTEXPR
|
||||
# define FMT_CONSTEXPR constexpr
|
||||
# define FMT_CONSTEXPR_VAR constexpr
|
||||
#else
|
||||
# define FMT_CONSTEXPR inline
|
||||
# define FMT_CONSTEXPR_VAR
|
||||
#endif
|
||||
|
||||
#ifndef FMT_OVERRIDE
|
||||
@ -855,23 +861,23 @@ using wcontext = buffer_context_t<wchar_t>;
|
||||
|
||||
namespace internal {
|
||||
template <typename Context, typename T>
|
||||
FMT_CONSTEXPR type get_type() {
|
||||
struct get_type {
|
||||
using value_type = decltype(make_value<Context>(std::declval<T>()));
|
||||
return value_type::type_tag;
|
||||
}
|
||||
static const type value = value_type::type_tag;
|
||||
};
|
||||
|
||||
template <typename Context>
|
||||
FMT_CONSTEXPR uint64_t get_types() { return 0; }
|
||||
|
||||
template <typename Context, typename Arg, typename... Args>
|
||||
FMT_CONSTEXPR uint64_t get_types() {
|
||||
return get_type<Context, Arg>() | (get_types<Context, Args...>() << 4);
|
||||
return get_type<Context, Arg>::value | (get_types<Context, Args...>() << 4);
|
||||
}
|
||||
|
||||
template <typename Context, typename T>
|
||||
FMT_CONSTEXPR basic_arg<Context> make_arg(const T &value) {
|
||||
basic_arg<Context> arg;
|
||||
arg.type_ = get_type<Context, T>();
|
||||
arg.type_ = get_type<Context, T>::value;
|
||||
arg.value_ = make_value<Context>(value);
|
||||
return arg;
|
||||
}
|
||||
|
@ -2044,7 +2044,7 @@ FMT_CONSTEXPR bool check_format_string(
|
||||
// because of a bug in MSVC.
|
||||
template <typename Context, typename T>
|
||||
struct format_type :
|
||||
std::integral_constant<bool, get_type<Context, T>() != CUSTOM> {};
|
||||
std::integral_constant<bool, get_type<Context, T>::value != CUSTOM> {};
|
||||
|
||||
// Specifies whether to format enums.
|
||||
template <typename T, typename Enable = void>
|
||||
@ -2335,7 +2335,7 @@ class basic_writer {
|
||||
void on_num() {
|
||||
unsigned num_digits = internal::count_digits(abs_value);
|
||||
char_type sep = internal::thousands_sep<char_type>(writer.locale_.get());
|
||||
static FMT_CONSTEXPR unsigned SEP_SIZE = 1;
|
||||
enum { SEP_SIZE = 1 };
|
||||
unsigned size = num_digits + SEP_SIZE * ((num_digits - 1) / 3);
|
||||
writer.write_int(size, get_prefix(), spec, [this, size, sep](auto &&it) {
|
||||
basic_string_view<char_type> s(&sep, SEP_SIZE);
|
||||
@ -2828,7 +2828,7 @@ struct formatter<
|
||||
FMT_CONSTEXPR typename ParseContext::iterator parse(ParseContext &ctx) {
|
||||
auto it = internal::null_terminating_iterator<Char>(ctx);
|
||||
using handler_type = internal::dynamic_specs_handler<ParseContext>;
|
||||
auto type = internal::get_type<buffer_context_t<Char>, T>();
|
||||
auto type = internal::get_type<buffer_context_t<Char>, T>::value;
|
||||
internal::specs_checker<handler_type>
|
||||
handler(handler_type(specs_, ctx), type);
|
||||
it = parse_format_specs(it, handler);
|
||||
@ -2933,7 +2933,7 @@ struct dynamic_formatter {
|
||||
void on_hash() {}
|
||||
};
|
||||
internal::specs_checker<null_handler>
|
||||
checker(null_handler(), internal::get_type<FormatContext, T>());
|
||||
checker(null_handler(), internal::get_type<FormatContext, T>::value);
|
||||
checker.on_align(specs_.align());
|
||||
if (specs_.flags_ == 0) {
|
||||
// Do nothing.
|
||||
@ -3068,9 +3068,9 @@ class format_spec_factory {
|
||||
}
|
||||
};
|
||||
|
||||
FMT_CONSTEXPR fill_spec_factory fill;
|
||||
FMT_CONSTEXPR format_spec_factory<width_spec> width;
|
||||
FMT_CONSTEXPR format_spec_factory<type_spec> type;
|
||||
static const fill_spec_factory fill;
|
||||
static const format_spec_factory<width_spec> width;
|
||||
static const format_spec_factory<type_spec> type;
|
||||
|
||||
template <typename It, typename Char>
|
||||
struct arg_join {
|
||||
@ -3216,7 +3216,7 @@ template <typename String, typename... Args>
|
||||
inline typename std::enable_if<
|
||||
std::is_base_of<internal::format_string, String>::value, std::string>::type
|
||||
format(String format_str, const Args & ... args) {
|
||||
FMT_CONSTEXPR bool invalid_format =
|
||||
FMT_CONSTEXPR_VAR bool invalid_format =
|
||||
internal::check_format_string<char, internal::error_handler, Args...>(
|
||||
string_view(format_str.value(), format_str.size()));
|
||||
(void)invalid_format;
|
||||
@ -3243,8 +3243,8 @@ class udl_formatter {
|
||||
public:
|
||||
template <typename... Args>
|
||||
std::basic_string<Char> operator()(const Args &... args) const {
|
||||
FMT_CONSTEXPR Char s[] = {CHARS..., '\0'};
|
||||
FMT_CONSTEXPR bool invalid_format =
|
||||
FMT_CONSTEXPR_VAR Char s[] = {CHARS..., '\0'};
|
||||
FMT_CONSTEXPR_VAR bool invalid_format =
|
||||
check_format_string<Char, error_handler, Args...>(
|
||||
basic_string_view<Char>(s, sizeof...(CHARS)));
|
||||
(void)invalid_format;
|
||||
|
@ -1598,6 +1598,30 @@ TEST(FormatTest, DynamicFormatter) {
|
||||
format_error, "precision not allowed for this argument type");
|
||||
}
|
||||
|
||||
TEST(FormatTest, UdlTemplate) {
|
||||
EXPECT_EQ("foo", "foo"_format());
|
||||
EXPECT_EQ(" 42", "{0:10}"_format(42));
|
||||
EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42));
|
||||
}
|
||||
|
||||
TEST(FormatTest, ToString) {
|
||||
EXPECT_EQ("42", fmt::to_string(42));
|
||||
}
|
||||
|
||||
TEST(FormatTest, OutputIterators) {
|
||||
std::list<char> out;
|
||||
fmt::format_to(std::back_inserter(out), "{}", 42);
|
||||
EXPECT_EQ("42", std::string(out.begin(), out.end()));
|
||||
std::stringstream s;
|
||||
fmt::format_to(std::ostream_iterator<char>(s), "{}", 42);
|
||||
EXPECT_EQ("42", s.str());
|
||||
}
|
||||
|
||||
TEST(FormatTest, OutputSize) {
|
||||
EXPECT_EQ(2, fmt::count("{}", 42));
|
||||
}
|
||||
|
||||
#if FMT_USE_CONSTEXPR
|
||||
struct test_arg_id_handler {
|
||||
enum result { NONE, EMPTY, INDEX, NAME, ERROR };
|
||||
result res = NONE;
|
||||
@ -1834,12 +1858,6 @@ TEST(FormatTest, ConstexprParseFormatString) {
|
||||
static_assert(parse_string("{:}"), "");
|
||||
}
|
||||
|
||||
TEST(FormatTest, UdlTemplate) {
|
||||
EXPECT_EQ("foo", "foo"_format());
|
||||
EXPECT_EQ(" 42", "{0:10}"_format(42));
|
||||
EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42));
|
||||
}
|
||||
|
||||
struct test_error_handler {
|
||||
const char *&error;
|
||||
|
||||
@ -1936,20 +1954,4 @@ TEST(FormatTest, FormatStringErrors) {
|
||||
"cannot switch from automatic to manual argument indexing",
|
||||
int, int);
|
||||
}
|
||||
|
||||
TEST(FormatTest, ToString) {
|
||||
EXPECT_EQ("42", fmt::to_string(42));
|
||||
}
|
||||
|
||||
TEST(FormatTest, OutputIterators) {
|
||||
std::list<char> out;
|
||||
fmt::format_to(std::back_inserter(out), "{}", 42);
|
||||
EXPECT_EQ("42", std::string(out.begin(), out.end()));
|
||||
std::stringstream s;
|
||||
fmt::format_to(std::ostream_iterator<char>(s), "{}", 42);
|
||||
EXPECT_EQ("42", s.str());
|
||||
}
|
||||
|
||||
TEST(FormatTest, OutputSize) {
|
||||
EXPECT_EQ(2, fmt::count("{}", 42));
|
||||
}
|
||||
#endif // FMT_USE_CONSTEXPR
|
||||
|
Loading…
Reference in New Issue
Block a user