diff --git a/include/fmt/base.h b/include/fmt/base.h index 51a4afa8..0d97dc7b 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -216,15 +216,15 @@ # define FMT_DEPRECATED /* deprecated */ #endif -#ifndef FMT_NO_UNIQUE_ADDRESS -# if FMT_CPLUSPLUS >= 202002L -# if FMT_HAS_CPP_ATTRIBUTE(no_unique_address) -# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]] +#ifdef FMT_NO_UNIQUE_ADDRESS +// Use the provided definition. +#elif FMT_CPLUSPLUS < 202002L +// Not supported. +#elif FMT_HAS_CPP_ATTRIBUTE(no_unique_address) +# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]] // VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485). -# elif (FMT_MSC_VERSION >= 1929) && !FMT_CLANG_VERSION -# define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] -# endif -# endif +#elif FMT_MSC_VERSION >= 1929 && !FMT_CLANG_VERSION +# define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] #endif #ifndef FMT_NO_UNIQUE_ADDRESS # define FMT_NO_UNIQUE_ADDRESS @@ -633,14 +633,31 @@ template class basic_string_view { } }; -FMT_EXPORT -using string_view = basic_string_view; +FMT_EXPORT using string_view = basic_string_view; /// Specifies if `T` is a character type. Can be specialized by users. -FMT_EXPORT template struct is_char : std::false_type {}; template <> struct is_char : std::true_type {}; +template class basic_appender; + +class context; +template class generic_context; + +template +using buffered_context = + conditional_t::value, context, + generic_context, Char>>; + +template struct arg_mapper; +FMT_EXPORT template class basic_format_arg; +FMT_EXPORT template class basic_format_args; +FMT_EXPORT template class dynamic_format_arg_store; + +// A separate type would result in shorter symbols but break ABI compatibility +// between clang and gcc on ARM (#1919). +using format_args = basic_format_args; + namespace detail { // Constructs fmt::basic_string_view from types implicitly convertible @@ -747,6 +764,47 @@ enum { cstring_set = set(type::cstring_type), pointer_set = set(type::pointer_type) }; + +struct view {}; + +template struct named_arg : view { + const Char* name; + const T& value; + named_arg(const Char* n, const T& v) : name(n), value(v) {} +}; + +template struct named_arg_info { + const Char* name; + int id; +}; + +template struct is_named_arg : std::false_type {}; +template struct is_statically_named_arg : std::false_type {}; + +template +struct is_named_arg> : std::true_type {}; + +template +auto unwrap_named_arg(const named_arg& arg) -> const T& { + return arg.value; +} +template >::value)> +auto unwrap_named_arg(T&& value) -> T&& { + return value; +} + +template constexpr auto count() -> size_t { return B ? 1 : 0; } +template constexpr auto count() -> size_t { + return (B1 ? 1 : 0) + count(); +} + +template constexpr auto count_named_args() -> size_t { + return count::value...>(); +} +template constexpr auto count_static_named_args() -> size_t { + return count::value...>(); +} } // namespace detail /// Reports a format error at compile time or, via a `format_error` exception, @@ -1768,9 +1826,8 @@ FMT_CONSTEXPR void parse_context::do_check_arg_id(int id) { // formatting has its own validation. if (detail::is_constant_evaluated() && (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) { - using context = detail::compile_parse_context; - if (id >= static_cast(this)->num_args()) - report_error("argument not found"); + auto ctx = static_cast*>(this); + if (id >= ctx->num_args()) report_error("argument not found"); } } @@ -1778,29 +1835,11 @@ template FMT_CONSTEXPR void parse_context::check_dynamic_spec(int arg_id) { if (detail::is_constant_evaluated() && (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) { - using context = detail::compile_parse_context; - static_cast(this)->check_dynamic_spec(arg_id); + auto ctx = static_cast*>(this); + ctx->check_dynamic_spec(arg_id); } } -FMT_EXPORT template class basic_format_arg; -FMT_EXPORT template class basic_format_args; -FMT_EXPORT template class dynamic_format_arg_store; - -class context; -template class generic_context; - -template class basic_appender; - -template -using buffered_context = - conditional_t::value, context, - generic_context, Char>>; - -// A separate type would result in shorter symbols but break ABI compatibility -// between clang and gcc on ARM (#1919). -using format_args = basic_format_args; - // A formatter for objects of type T. FMT_EXPORT template @@ -1929,47 +1968,6 @@ auto get_iterator(buffer&, OutputIt out) -> OutputIt { return out; } -struct view {}; - -template struct named_arg : view { - const Char* name; - const T& value; - named_arg(const Char* n, const T& v) : name(n), value(v) {} -}; - -template struct named_arg_info { - const Char* name; - int id; -}; - -template struct is_named_arg : std::false_type {}; -template struct is_statically_named_arg : std::false_type {}; - -template -struct is_named_arg> : std::true_type {}; - -template -auto unwrap_named_arg(const named_arg& arg) -> const T& { - return arg.value; -} -template >::value)> -auto unwrap_named_arg(T&& value) -> T&& { - return value; -} - -template constexpr auto count() -> size_t { return B ? 1 : 0; } -template constexpr auto count() -> size_t { - return (B1 ? 1 : 0) + count(); -} - -template constexpr auto count_named_args() -> size_t { - return count::value...>(); -} -template constexpr auto count_static_named_args() -> size_t { - return count::value...>(); -} - struct unformattable {}; struct unformattable_char : unformattable {}; struct unformattable_pointer : unformattable {};