From 5de0bc1d4f2e7a750f050ca2e80ab95586f96d8e Mon Sep 17 00:00:00 2001 From: Alexey Ochapov Date: Tue, 8 Dec 2020 02:53:11 +0300 Subject: [PATCH] Add UDL as replacement for FMT_COMPILE (#2043) --- include/fmt/compile.h | 38 ++++++++++++++++++++++++++++++++++++++ test/compile-test.cc | 8 ++++++++ 2 files changed, 46 insertions(+) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index affd793e..65aeb445 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -13,6 +13,15 @@ #include "format.h" +#ifndef FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +# if defined(__cpp_nontype_template_parameter_class) && \ + (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 903) +# define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 1 +# else +# define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 0 +# endif +#endif + FMT_BEGIN_NAMESPACE namespace detail { @@ -37,6 +46,24 @@ struct is_compiled_string : std::is_base_of {}; */ #define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string) +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +template struct fixed_string { + constexpr fixed_string(const Char (&str)[N]) { + copy_str(static_cast(str), str + N, + data); + } + Char data[N]{}; +}; + +template Str> +struct udl_compiled_string : compiled_string { + using char_type = Char; + constexpr operator basic_string_view() const { + return {Str.data, N - 1}; + } +}; +#endif + template const T& first(const T& value, const Tail&...) { return value; @@ -698,6 +725,17 @@ size_t formatted_size(const CompiledFormat& cf, const Args&... args) { return format_to(detail::counting_iterator(), cf, args...).count(); } +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +inline namespace literals { +template +constexpr detail::udl_compiled_string, + sizeof(Str.data), Str> +operator""_cf() { + return {}; +} +} // namespace literals +#endif + FMT_END_NAMESPACE #endif // FMT_COMPILE_H_ diff --git a/test/compile-test.cc b/test/compile-test.cc index 479de061..4038ac58 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -179,6 +179,14 @@ TEST(CompileTest, Empty) { } #endif +#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS +TEST(CompileTest, CompileFormatStringLiteral) { + using namespace fmt::literals; + EXPECT_EQ("", fmt::format(""_cf)); + EXPECT_EQ("42", fmt::format("{}"_cf, 42)); +} +#endif + #if __cplusplus >= 202002L template struct test_string { template constexpr bool operator==(const T& rhs) const noexcept {