diff --git a/dist/trunk/emio.hpp b/dist/trunk/emio.hpp index 7f97533..d46100d 100644 --- a/dist/trunk/emio.hpp +++ b/dist/trunk/emio.hpp @@ -3264,6 +3264,8 @@ inline constexpr runtime_string runtime(const std::string_view& s) noexcept { // // For the license information refer to emio.hpp +#include + // // Copyright (c) 2021 - present, Toni Neubert // All rights reserved. @@ -4624,16 +4626,19 @@ constexpr result write_arg(writer& out, format_specs& specs, const Arg arg }); } +template +inline constexpr bool is_void_pointer_v = + std::is_pointer_v && std::is_same_v>, void>; + template - requires(std::is_same_v || std::is_same_v) + requires(is_void_pointer_v || std::is_null_pointer_v) constexpr result write_arg(writer& out, format_specs& specs, Arg arg) noexcept { specs.alternate_form = true; specs.type = 'x'; - if constexpr (std::is_same_v) { + if constexpr (std::is_null_pointer_v) { return write_arg(out, specs, uintptr_t{0}); } else { - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): valid cast - return write_arg(out, specs, reinterpret_cast(arg)); + return write_arg(out, specs, std::bit_cast(arg)); } } @@ -4916,7 +4921,7 @@ template inline constexpr bool is_core_type_v = std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || std::is_same_v; + std::is_null_pointer_v || is_void_pointer_v || std::is_same_v; template concept has_format_as = requires(T arg) { format_as(arg); }; @@ -4934,7 +4939,7 @@ struct unified_type { }; template - requires(!std::is_integral_v && !std::is_same_v && std::is_constructible_v) + requires(!std::is_integral_v && !std::is_null_pointer_v && std::is_constructible_v) struct unified_type { using type = std::string_view; }; @@ -4952,8 +4957,7 @@ struct unified_type { }; template - requires(std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v) + requires(std::is_same_v || std::is_same_v || is_void_pointer_v || std::is_null_pointer_v) struct unified_type { using type = T; }; @@ -5041,7 +5045,7 @@ class formatter { EMIO_TRYV(check_bool_specs(specs)); } else if constexpr (std::is_same_v) { EMIO_TRYV(check_char_specs(specs)); - } else if constexpr (std::is_same_v || std::is_same_v) { + } else if constexpr (detail::format::is_void_pointer_v || std::is_null_pointer_v) { EMIO_TRYV(check_pointer_specs(specs)); } else if constexpr (std::is_integral_v) { EMIO_TRYV(check_integral_specs(specs)); @@ -5239,6 +5243,31 @@ class formatter> { formatter underlying_{}; }; +/** + * Converts a value of a pointer-like type to const void * for pointer formatting. + * @param p The value of the pointer. + * @return The const void* version of the pointer. + */ +template + requires(std::is_pointer_v) +constexpr auto ptr(T p) noexcept { + if constexpr (std::is_volatile_v>) { + return static_cast(p); + } else { + return static_cast(p); + } +} + +template +constexpr const void* ptr(const std::unique_ptr& p) { + return p.get(); +} + +template +const void* ptr(const std::shared_ptr& p) { + return p.get(); +} + } // namespace emio namespace emio::detail::format {