This commit is contained in:
Victor Zverovich 2024-09-06 12:27:48 -07:00
parent cad876be4c
commit f5a16a484b
8 changed files with 24 additions and 60 deletions

View File

@ -73,12 +73,7 @@ class dynamic_arg_list {
* into type-erased formatting functions such as `fmt::vformat`. * into type-erased formatting functions such as `fmt::vformat`.
*/ */
template <typename Context> template <typename Context>
class dynamic_format_arg_store class dynamic_format_arg_store {
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
// Workaround a GCC template argument substitution bug.
: public basic_format_args<Context>
#endif
{
private: private:
using char_type = typename Context::char_type; using char_type = typename Context::char_type;
@ -97,7 +92,7 @@ class dynamic_format_arg_store
}; };
template <typename T> template <typename T>
using stored_type = conditional_t< using stored_t = conditional_t<
std::is_convertible<T, std::basic_string<char_type>>::value && std::is_convertible<T, std::basic_string<char_type>>::value &&
!detail::is_reference_wrapper<T>::value, !detail::is_reference_wrapper<T>::value,
std::basic_string<char_type>, T>; std::basic_string<char_type>, T>;
@ -122,10 +117,8 @@ class dynamic_format_arg_store
template <typename T> template <typename T>
void emplace_arg(const detail::named_arg<char_type, T>& arg) { void emplace_arg(const detail::named_arg<char_type, T>& arg) {
if (named_info_.empty()) { if (named_info_.empty())
constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr}; data_.insert(data_.begin(), basic_format_arg<Context>(nullptr, 0));
data_.insert(data_.begin(), basic_format_arg<Context>(zero_ptr, 0));
}
data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value))); data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
auto pop_one = [](std::vector<basic_format_arg<Context>>* data) { auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
data->pop_back(); data->pop_back();
@ -162,7 +155,7 @@ class dynamic_format_arg_store
*/ */
template <typename T> void push_back(const T& arg) { template <typename T> void push_back(const T& arg) {
if (detail::const_check(need_copy<T>::value)) if (detail::const_check(need_copy<T>::value))
emplace_arg(dynamic_args_.push<stored_type<T>>(arg)); emplace_arg(dynamic_args_.push<stored_t<T>>(arg));
else else
emplace_arg(detail::unwrap(arg)); emplace_arg(detail::unwrap(arg));
} }
@ -198,7 +191,7 @@ class dynamic_format_arg_store
dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str(); dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
if (detail::const_check(need_copy<T>::value)) { if (detail::const_check(need_copy<T>::value)) {
emplace_arg( emplace_arg(
fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value))); fmt::arg(arg_name, dynamic_args_.push<stored_t<T>>(arg.value)));
} else { } else {
emplace_arg(fmt::arg(arg_name, arg.value)); emplace_arg(fmt::arg(arg_name, arg.value));
} }

View File

@ -140,17 +140,14 @@ FMT_END_NAMESPACE
# endif # endif
#endif #endif
#ifndef FMT_USE_USER_DEFINED_LITERALS #ifndef FMT_USE_USER_LITERALS
// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs. // EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
// # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION || \
// GCC before 4.9 requires a space in `operator"" _a` which is invalid in later
// compiler versions.
# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 409 || \
FMT_MSC_VERSION >= 1900) && \ FMT_MSC_VERSION >= 1900) && \
(!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480) (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
# define FMT_USE_USER_DEFINED_LITERALS 1 # define FMT_USE_USER_LITERALS 1
# else # else
# define FMT_USE_USER_DEFINED_LITERALS 0 # define FMT_USE_USER_LITERALS 0
# endif # endif
#endif #endif
@ -3775,7 +3772,7 @@ FMT_CONSTEXPR void handle_dynamic_spec(
if (kind != arg_id_kind::none) value = get_dynamic_spec(kind, ref, ctx); if (kind != arg_id_kind::none) value = get_dynamic_spec(kind, ref, ctx);
} }
#if FMT_USE_USER_DEFINED_LITERALS #if FMT_USE_USER_LITERALS
# if FMT_USE_NONTYPE_TEMPLATE_ARGS # if FMT_USE_NONTYPE_TEMPLATE_ARGS
template <typename T, typename Char, size_t N, template <typename T, typename Char, size_t N,
fmt::detail_exported::fixed_string<Char, N> Str> fmt::detail_exported::fixed_string<Char, N> Str>
@ -3810,8 +3807,8 @@ template <typename Char> struct udl_arg {
return {str, std::forward<T>(value)}; return {str, std::forward<T>(value)};
} }
}; };
# endif # endif // FMT_USE_NONTYPE_TEMPLATE_ARGS
#endif // FMT_USE_USER_DEFINED_LITERALS #endif // FMT_USE_USER_LITERALS
template <typename Char> struct format_handler { template <typename Char> struct format_handler {
parse_context<Char> parse_ctx; parse_context<Char> parse_ctx;
@ -4294,7 +4291,7 @@ struct formatter<detail::float128, Char>
: detail::native_formatter<detail::float128, Char, : detail::native_formatter<detail::float128, Char,
detail::type::float_type> {}; detail::type::float_type> {};
#if FMT_USE_USER_DEFINED_LITERALS #if FMT_USE_USER_LITERALS
inline namespace literals { inline namespace literals {
/** /**
* User-defined literal equivalent of `fmt::arg`. * User-defined literal equivalent of `fmt::arg`.
@ -4315,7 +4312,7 @@ constexpr auto operator""_a(const char* s, size_t) -> detail::udl_arg<char> {
} }
# endif # endif
} // namespace literals } // namespace literals
#endif // FMT_USE_USER_DEFINED_LITERALS #endif // FMT_USE_USER_LITERALS
FMT_API auto vformat(string_view fmt, format_args args) -> std::string; FMT_API auto vformat(string_view fmt, format_args args) -> std::string;

View File

@ -147,8 +147,8 @@ FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
* } * }
*/ */
template <typename... T> template <typename... T>
std::system_error windows_error(int error_code, string_view message, auto windows_error(int error_code, string_view message,
const T&... args) { const T&... args) -> std::system_error {
return vwindows_error(error_code, message, vargs<T...>{{args...}}); return vwindows_error(error_code, message, vargs<T...>{{args...}});
} }

View File

@ -89,7 +89,7 @@ constexpr auto make_wformat_args(T&... args)
} }
inline namespace literals { inline namespace literals {
#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS #if FMT_USE_USER_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS
constexpr auto operator""_a(const wchar_t* s, size_t) constexpr auto operator""_a(const wchar_t* s, size_t)
-> detail::udl_arg<wchar_t> { -> detail::udl_arg<wchar_t> {
return {s}; return {s};

View File

@ -198,7 +198,7 @@ class CxxHandler(BaseHandler):
PREDEFINED = _WIN32=1 \ PREDEFINED = _WIN32=1 \
__linux__=1 \ __linux__=1 \
FMT_ENABLE_IF(...)= \ FMT_ENABLE_IF(...)= \
FMT_USE_USER_DEFINED_LITERALS=1 \ FMT_USE_USER_LITERALS=1 \
FMT_USE_ALIAS_TEMPLATES=1 \ FMT_USE_ALIAS_TEMPLATES=1 \
FMT_USE_NONTYPE_TEMPLATE_ARGS=1 \ FMT_USE_NONTYPE_TEMPLATE_ARGS=1 \
FMT_API= \ FMT_API= \

View File

@ -115,8 +115,7 @@ function (run_tests)
endif () endif ()
endfunction () endfunction ()
# Check if the source file skeleton compiles.
# check if the source file skeleton compiles
expect_compile(check "") expect_compile(check "")
expect_compile(check-error "compilation_error" ERROR) expect_compile(check-error "compilation_error" ERROR)
@ -166,31 +165,6 @@ expect_compile(format-lots-of-arguments-with-function "
fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, f); fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, f);
" ERROR) " ERROR)
# Check if user-defined literals are available
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_FLAGS ${CXX_STANDARD_FLAG})
check_cxx_source_compiles("
void operator\"\" _udl(long double);
int main() {}"
SUPPORTS_USER_DEFINED_LITERALS)
set(CMAKE_REQUIRED_FLAGS )
if (NOT SUPPORTS_USER_DEFINED_LITERALS)
set (SUPPORTS_USER_DEFINED_LITERALS OFF)
endif ()
# Make sure that compiler features detected in the header
# match the features detected in CMake.
if (SUPPORTS_USER_DEFINED_LITERALS)
set(supports_udl 1)
else ()
set(supports_udl 0)
endif ()
expect_compile(udl-check "
#if FMT_USE_USER_DEFINED_LITERALS != ${supports_udl}
# error
#endif
")
if (CMAKE_CXX_STANDARD GREATER_EQUAL 20) if (CMAKE_CXX_STANDARD GREATER_EQUAL 20)
# Compile-time argument type check # Compile-time argument type check
expect_compile(format-string-number-spec " expect_compile(format-string-number-spec "

View File

@ -2005,7 +2005,7 @@ TEST(format_test, custom_format_compile_time_string) {
EXPECT_EQ(fmt::format(FMT_STRING("{}"), const_answer), "42"); EXPECT_EQ(fmt::format(FMT_STRING("{}"), const_answer), "42");
} }
#if FMT_USE_USER_DEFINED_LITERALS #if FMT_USE_USER_LITERALS
TEST(format_test, named_arg_udl) { TEST(format_test, named_arg_udl) {
using namespace fmt::literals; using namespace fmt::literals;
auto udl_a = fmt::format("{first}{second}{first}{third}", "first"_a = "abra", auto udl_a = fmt::format("{first}{second}{first}{third}", "first"_a = "abra",
@ -2017,7 +2017,7 @@ TEST(format_test, named_arg_udl) {
EXPECT_EQ(fmt::format("{answer}", "answer"_a = Answer()), "42"); EXPECT_EQ(fmt::format("{answer}", "answer"_a = Answer()), "42");
} }
#endif // FMT_USE_USER_DEFINED_LITERALS #endif // FMT_USE_USER_LITERALS
TEST(format_test, enum) { EXPECT_EQ(fmt::format("{}", foo), "0"); } TEST(format_test, enum) { EXPECT_EQ(fmt::format("{}", foo), "0"); }

View File

@ -231,7 +231,7 @@ TEST(format_test, wide_format_to_n) {
EXPECT_EQ(L"BC x", fmt::wstring_view(buffer, 4)); EXPECT_EQ(L"BC x", fmt::wstring_view(buffer, 4));
} }
#if FMT_USE_USER_DEFINED_LITERALS #if FMT_USE_USER_LITERALS
TEST(xchar_test, named_arg_udl) { TEST(xchar_test, named_arg_udl) {
using namespace fmt::literals; using namespace fmt::literals;
auto udl_a = auto udl_a =
@ -242,7 +242,7 @@ TEST(xchar_test, named_arg_udl) {
fmt::arg(L"second", L"cad"), fmt::arg(L"third", 99)), fmt::arg(L"second", L"cad"), fmt::arg(L"third", 99)),
udl_a); udl_a);
} }
#endif // FMT_USE_USER_DEFINED_LITERALS #endif // FMT_USE_USER_LITERALS
TEST(xchar_test, print) { TEST(xchar_test, print) {
// Check that the wide print overload compiles. // Check that the wide print overload compiles.