Relax constexpr requirements

This commit is contained in:
Victor Zverovich 2018-02-04 08:52:43 -08:00
parent dc5403612e
commit 1f57243b49
3 changed files with 52 additions and 44 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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