Add UDL as replacement for FMT_COMPILE (#2043)

This commit is contained in:
Alexey Ochapov 2020-12-08 02:53:11 +03:00 committed by GitHub
parent a6fafe2f01
commit 5de0bc1d4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 0 deletions

View File

@ -13,6 +13,15 @@
#include "format.h" #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 FMT_BEGIN_NAMESPACE
namespace detail { namespace detail {
@ -37,6 +46,24 @@ struct is_compiled_string : std::is_base_of<compiled_string, S> {};
*/ */
#define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string) #define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string)
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
template <typename Char, size_t N> struct fixed_string {
constexpr fixed_string(const Char (&str)[N]) {
copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str), str + N,
data);
}
Char data[N]{};
};
template <typename Char, size_t N, fixed_string<Char, N> Str>
struct udl_compiled_string : compiled_string {
using char_type = Char;
constexpr operator basic_string_view<char_type>() const {
return {Str.data, N - 1};
}
};
#endif
template <typename T, typename... Tail> template <typename T, typename... Tail>
const T& first(const T& value, const Tail&...) { const T& first(const T& value, const Tail&...) {
return value; 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(); return format_to(detail::counting_iterator(), cf, args...).count();
} }
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
inline namespace literals {
template <detail::fixed_string Str>
constexpr detail::udl_compiled_string<remove_cvref_t<decltype(Str.data[0])>,
sizeof(Str.data), Str>
operator""_cf() {
return {};
}
} // namespace literals
#endif
FMT_END_NAMESPACE FMT_END_NAMESPACE
#endif // FMT_COMPILE_H_ #endif // FMT_COMPILE_H_

View File

@ -179,6 +179,14 @@ TEST(CompileTest, Empty) {
} }
#endif #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 #if __cplusplus >= 202002L
template <size_t max_string_length> struct test_string { template <size_t max_string_length> struct test_string {
template <typename T> constexpr bool operator==(const T& rhs) const noexcept { template <typename T> constexpr bool operator==(const T& rhs) const noexcept {