From 1f7beec900e458060f5ceadbba017e030cd0d192 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 5 Aug 2023 01:05:08 +0500 Subject: [PATCH] Improve addressof() Signed-off-by: Vladislav Shchapov --- include/fmt/core.h | 66 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index e0668b7796f7b..d5290c8e06e7e 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -104,6 +104,22 @@ # define FMT_CONSTEXPR #endif +#if FMT_MSC_VERSION && _MSC_FULL_VER >= 190024215 +# define FMT_HAS_BUILTIN_ADDRESSOF +#elif FMT_GCC_VERSION >= 700 +# define FMT_HAS_BUILTIN_ADDRESSOF +#elif defined(__has_builtin) +# if __has_builtin(__builtin_addressof) +# define FMT_HAS_BUILTIN_ADDRESSOF +# endif +#endif + +#if FMT_CPLUSPLUS >= 201703L && defined(FMT_HAS_BUILTIN_ADDRESSOF) +# define FMT_CONSTEXPR_BUILTIN_ADDRESSOF constexpr +#else +# define FMT_CONSTEXPR_BUILTIN_ADDRESSOF +#endif + #if ((FMT_CPLUSPLUS >= 202002L) && \ (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE > 9)) || \ (FMT_CPLUSPLUS >= 201709L && FMT_GCC_VERSION >= 1002) @@ -1233,6 +1249,23 @@ template struct custom_value { void (*format)(void* arg, parse_context& parse_ctx, Context& ctx); }; +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 +// A workaround for gcc 4.8 to make void_t work in a SFINAE context. +template struct void_t_impl { + using type = void; +}; +template using void_t = typename void_t_impl::type; +#else +template using void_t = void; +#endif + +template +struct has_address_operator : std::false_type {}; + +template +struct has_address_operator())>> + : std::true_type {}; + // A formatting argument value. template class value { public: @@ -1281,15 +1314,16 @@ template class value { FMT_INLINE value(const named_arg_info* args, size_t size) : named_args{args, size} {} - template FMT_CONSTEXPR FMT_INLINE value(T& val) { + // Workaround for types with overloaded operator&. + // std::addressof is non-constexpr before C++17. + template ::value)> + FMT_CONSTEXPR_BUILTIN_ADDRESSOF FMT_INLINE value(T& val) { using value_type = remove_const_t; -#if defined(_LIBCPP_VERSION) - // Workaround for formatter::reference, Char>. - // libc++ std::vector::reference has an overloaded operator&. - // std::addressof is non-constexpr before C++17. +#ifdef FMT_HAS_BUILTIN_ADDRESSOF custom.value = const_cast(__builtin_addressof(val)); #else - custom.value = const_cast(&val); + custom.value = reinterpret_cast( + const_cast(&reinterpret_cast(val))); #endif // Get the formatter type through the context to allow different contexts // have different extension points, e.g. `formatter` for `format` and @@ -1297,6 +1331,18 @@ template class value { custom.format = format_custom_arg< value_type, typename Context::template formatter_type>; } + + template ::value)> + FMT_CONSTEXPR FMT_INLINE value(T& val) { + using value_type = remove_const_t; + custom.value = const_cast(&val); + // Get the formatter type through the context to allow different contexts + // have different extension points, e.g. `formatter` for `format` and + // `printf_formatter` for `printf`. + custom.format = format_custom_arg< + value_type, typename Context::template formatter_type>; + } + value(unformattable); value(unformattable_char); value(unformattable_pointer); @@ -1509,14 +1555,6 @@ FMT_CONSTEXPR auto copy_str(R&& rng, OutputIt out) -> OutputIt { return detail::copy_str(rng.begin(), rng.end(), out); } -#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 -// A workaround for gcc 4.8 to make void_t work in a SFINAE context. -template struct void_t_impl { using type = void; }; -template using void_t = typename void_t_impl::type; -#else -template using void_t = void; -#endif - template struct is_output_iterator : std::false_type {};