forked from fmtlib/fmt
Support compile-time strings and compile-time format string compilation in module
Make just the necessary parts available for lookup from client context.
This commit is contained in:
committed by
Victor Zverovich
parent
3423d75475
commit
0193e7c428
@ -164,7 +164,8 @@ struct is_compiled_string : std::is_base_of<compiled_string, S> {};
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||||
template <typename Char, size_t N, fixed_string<Char, N> Str>
|
template <typename Char, size_t N,
|
||||||
|
fmt::detail_exported::fixed_string<Char, N> Str>
|
||||||
struct udl_compiled_string : compiled_string {
|
struct udl_compiled_string : compiled_string {
|
||||||
using char_type = Char;
|
using char_type = Char;
|
||||||
constexpr operator basic_string_view<char_type>() const {
|
constexpr operator basic_string_view<char_type>() const {
|
||||||
@ -622,7 +623,7 @@ void print(const S& format_str, const Args&... args) {
|
|||||||
|
|
||||||
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
template <detail::fixed_string Str>
|
template <detail_exported::fixed_string Str>
|
||||||
constexpr detail::udl_compiled_string<
|
constexpr detail::udl_compiled_string<
|
||||||
remove_cvref_t<decltype(Str.data[0])>,
|
remove_cvref_t<decltype(Str.data[0])>,
|
||||||
sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str>
|
sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str>
|
||||||
|
@ -778,6 +778,33 @@ FMT_INLINE auto make_args_checked(const S& fmt,
|
|||||||
return {args...};
|
return {args...};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compile-time support
|
||||||
|
namespace detail_exported {
|
||||||
|
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||||
|
template <typename Char, size_t N> struct fixed_string {
|
||||||
|
constexpr fixed_string(const Char (&str)[N]) {
|
||||||
|
detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str),
|
||||||
|
str + N, data);
|
||||||
|
}
|
||||||
|
Char data[N]{};
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Converts a compile-time string to basic_string_view.
|
||||||
|
template <typename Char, size_t N>
|
||||||
|
constexpr auto compile_string_to_view(const Char (&s)[N])
|
||||||
|
-> basic_string_view<Char> {
|
||||||
|
// Remove trailing NUL character if needed. Won't be present if this is used
|
||||||
|
// with a raw character array (i.e. not defined as a string).
|
||||||
|
return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
|
||||||
|
}
|
||||||
|
template <typename Char>
|
||||||
|
constexpr auto compile_string_to_view(detail::std_string_view<Char> s)
|
||||||
|
-> basic_string_view<Char> {
|
||||||
|
return {s.data(), s.size()};
|
||||||
|
}
|
||||||
|
} // namespace detail_exported
|
||||||
|
|
||||||
FMT_BEGIN_DETAIL_NAMESPACE
|
FMT_BEGIN_DETAIL_NAMESPACE
|
||||||
|
|
||||||
inline void throw_format_error(const char* message) {
|
inline void throw_format_error(const char* message) {
|
||||||
@ -2098,20 +2125,6 @@ FMT_CONSTEXPR void handle_dynamic_spec(int& value,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts a compile-time string to basic_string_view.
|
|
||||||
template <typename Char, size_t N>
|
|
||||||
constexpr auto compile_string_to_view(const Char (&s)[N])
|
|
||||||
-> basic_string_view<Char> {
|
|
||||||
// Remove trailing NUL character if needed. Won't be present if this is used
|
|
||||||
// with a raw character array (i.e. not defined as a string).
|
|
||||||
return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
|
|
||||||
}
|
|
||||||
template <typename Char>
|
|
||||||
constexpr auto compile_string_to_view(std_string_view<Char> s)
|
|
||||||
-> basic_string_view<Char> {
|
|
||||||
return {s.data(), s.size()};
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FMT_STRING_IMPL(s, base, explicit) \
|
#define FMT_STRING_IMPL(s, base, explicit) \
|
||||||
[] { \
|
[] { \
|
||||||
/* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
|
/* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
|
||||||
@ -2120,7 +2133,7 @@ constexpr auto compile_string_to_view(std_string_view<Char> s)
|
|||||||
using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
|
using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
|
||||||
FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
|
FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
|
||||||
operator fmt::basic_string_view<char_type>() const { \
|
operator fmt::basic_string_view<char_type>() const { \
|
||||||
return fmt::detail::compile_string_to_view<char_type>(s); \
|
return fmt::detail_exported::compile_string_to_view<char_type>(s); \
|
||||||
} \
|
} \
|
||||||
}; \
|
}; \
|
||||||
return FMT_COMPILE_STRING(); \
|
return FMT_COMPILE_STRING(); \
|
||||||
@ -2138,16 +2151,6 @@ constexpr auto compile_string_to_view(std_string_view<Char> s)
|
|||||||
*/
|
*/
|
||||||
#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string, )
|
#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_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]{};
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if FMT_USE_USER_DEFINED_LITERALS
|
#if FMT_USE_USER_DEFINED_LITERALS
|
||||||
template <typename Char> struct udl_formatter {
|
template <typename Char> struct udl_formatter {
|
||||||
basic_string_view<Char> str;
|
basic_string_view<Char> str;
|
||||||
@ -2159,7 +2162,8 @@ template <typename Char> struct udl_formatter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||||
template <typename T, typename Char, size_t N, fixed_string<Char, N> Str>
|
template <typename T, typename Char, size_t N,
|
||||||
|
fmt::detail_exported::fixed_string<Char, N> Str>
|
||||||
struct statically_named_arg : view {
|
struct statically_named_arg : view {
|
||||||
static constexpr auto name = Str.data;
|
static constexpr auto name = Str.data;
|
||||||
|
|
||||||
@ -2167,14 +2171,18 @@ struct statically_named_arg : view {
|
|||||||
statically_named_arg(const T& v) : value(v) {}
|
statically_named_arg(const T& v) : value(v) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Char, size_t N, fixed_string<Char, N> Str>
|
template <typename T, typename Char, size_t N,
|
||||||
|
fmt::detail_exported::fixed_string<Char, N> Str>
|
||||||
struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
|
struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
|
||||||
|
|
||||||
template <typename T, typename Char, size_t N, fixed_string<Char, N> Str>
|
template <typename T, typename Char, size_t N,
|
||||||
|
fmt::detail_exported::fixed_string<Char, N> Str>
|
||||||
struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
|
struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
|
||||||
: std::true_type {};
|
: std::true_type {};
|
||||||
|
|
||||||
template <typename Char, size_t N, fixed_string<Char, N> Str> struct udl_arg {
|
template <typename Char, size_t N,
|
||||||
|
fmt::detail_exported::fixed_string<Char, N> Str>
|
||||||
|
struct udl_arg {
|
||||||
template <typename T> auto operator=(T&& value) const {
|
template <typename T> auto operator=(T&& value) const {
|
||||||
return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
|
return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
|
||||||
}
|
}
|
||||||
@ -2721,7 +2729,7 @@ inline namespace literals {
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
|
||||||
template <detail::fixed_string Str>
|
template <detail_exported::fixed_string Str>
|
||||||
constexpr auto operator""_a()
|
constexpr auto operator""_a()
|
||||||
-> detail::udl_arg<remove_cvref_t<decltype(Str.data[0])>,
|
-> detail::udl_arg<remove_cvref_t<decltype(Str.data[0])>,
|
||||||
sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> {
|
sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> {
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
module;
|
module;
|
||||||
|
#ifndef __cpp_modules
|
||||||
|
# error Module not supported.
|
||||||
|
#endif
|
||||||
|
|
||||||
// put all implementation-provided headers into the global module fragment
|
// put all implementation-provided headers into the global module fragment
|
||||||
// to prevent attachment to this module
|
// to prevent attachment to this module
|
||||||
#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER)
|
#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER)
|
||||||
@ -76,10 +80,6 @@ export module fmt;
|
|||||||
} \
|
} \
|
||||||
export {
|
export {
|
||||||
|
|
||||||
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER > 192930036
|
|
||||||
#define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// all library-provided declarations and definitions
|
// all library-provided declarations and definitions
|
||||||
// must be in the module purview to be exported
|
// must be in the module purview to be exported
|
||||||
#include "fmt/args.h"
|
#include "fmt/args.h"
|
||||||
|
@ -445,3 +445,11 @@ TEST(module_test, has_formatter) {
|
|||||||
TEST(module_test, is_formattable) {
|
TEST(module_test, is_formattable) {
|
||||||
EXPECT_FALSE(fmt::is_formattable<disabled_formatter>::value);
|
EXPECT_FALSE(fmt::is_formattable<disabled_formatter>::value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(module_test, compile_format_string) {
|
||||||
|
using namespace fmt::literals;
|
||||||
|
EXPECT_EQ("42", fmt::format("{0:x}"_cf, 0x42));
|
||||||
|
EXPECT_EQ(L"42", fmt::format(L"{:}"_cf, 42));
|
||||||
|
EXPECT_EQ("4.2", fmt::format("{arg:3.1f}"_cf, "arg"_a = 4.2));
|
||||||
|
EXPECT_EQ(L" 42", fmt::format(L"{arg:>3}"_cf, L"arg"_a = L"42"));
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user