mirror of
https://github.com/fmtlib/fmt.git
synced 2024-12-24 12:14:26 +00:00
Enable FMT_STRING() use with types other than string literals
This commit is contained in:
parent
69779b4ed6
commit
664dd88e31
@ -371,6 +371,9 @@ template <typename Char> class basic_string_view {
|
||||
the size with ``std::char_traits<Char>::length``.
|
||||
\endrst
|
||||
*/
|
||||
#if __cplusplus >= 201703L // C++17's char_traits::length() is constexpr.
|
||||
FMT_CONSTEXPR
|
||||
#endif
|
||||
basic_string_view(const Char* s)
|
||||
: data_(s), size_(std::char_traits<Char>::length(s)) {}
|
||||
|
||||
|
@ -2238,6 +2238,7 @@ enum class arg_id_kind { none, index, name };
|
||||
// An argument reference.
|
||||
template <typename Char> struct arg_ref {
|
||||
FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {}
|
||||
|
||||
FMT_CONSTEXPR explicit arg_ref(int index)
|
||||
: kind(arg_id_kind::index), val(index) {}
|
||||
FMT_CONSTEXPR explicit arg_ref(basic_string_view<Char> name)
|
||||
@ -3525,9 +3526,21 @@ template <typename Char> struct udl_arg {
|
||||
}
|
||||
};
|
||||
|
||||
// Converts string literals to basic_string_view.
|
||||
template <typename Char, size_t N>
|
||||
FMT_CONSTEXPR basic_string_view<Char> literal_to_view(const Char (&s)[N]) {
|
||||
return {s, N - 1};
|
||||
FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
|
||||
const Char (&s)[N]) {
|
||||
// Remove trailing null character if needed. Won't be present if this is used
|
||||
// with 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)};
|
||||
}
|
||||
|
||||
// Converts string_view to basic_string_view.
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
|
||||
const std_string_view<Char>& s) {
|
||||
return {s.data(), s.size()};
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
@ -3589,11 +3602,10 @@ FMT_END_NAMESPACE
|
||||
[] { \
|
||||
/* Use a macro-like name to avoid shadowing warnings. */ \
|
||||
struct FMT_COMPILE_STRING : fmt::compile_string { \
|
||||
using char_type = fmt::remove_cvref_t<decltype(*s)>; \
|
||||
using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
|
||||
FMT_MAYBE_UNUSED __VA_ARGS__ FMT_CONSTEXPR \
|
||||
operator fmt::basic_string_view<char_type>() const { \
|
||||
/* FMT_STRING only accepts string literals. */ \
|
||||
return fmt::internal::literal_to_view(s); \
|
||||
return fmt::internal::compile_string_to_view<char_type>(s); \
|
||||
} \
|
||||
}; \
|
||||
return FMT_COMPILE_STRING(); \
|
||||
|
@ -46,6 +46,7 @@ using fmt::format_error;
|
||||
using fmt::memory_buffer;
|
||||
using fmt::string_view;
|
||||
using fmt::wmemory_buffer;
|
||||
using fmt::wstring_view;
|
||||
using fmt::internal::basic_writer;
|
||||
using fmt::internal::max_value;
|
||||
|
||||
@ -1854,10 +1855,23 @@ TEST(FormatTest, UnpackedArgs) {
|
||||
struct string_like {};
|
||||
fmt::string_view to_string_view(string_like) { return "foo"; }
|
||||
|
||||
constexpr char with_null[3] = {'{', '}', '\0'};
|
||||
constexpr char no_null[2] = {'{', '}'};
|
||||
|
||||
TEST(FormatTest, CompileTimeString) {
|
||||
EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42));
|
||||
EXPECT_EQ(L"42", fmt::format(FMT_STRING(L"{}"), 42));
|
||||
EXPECT_EQ("foo", fmt::format(FMT_STRING("{}"), string_like()));
|
||||
(void)with_null;
|
||||
(void)no_null;
|
||||
#if __cplusplus >= 201703L
|
||||
EXPECT_EQ("42", fmt::format(FMT_STRING(with_null), 42));
|
||||
EXPECT_EQ("42", fmt::format(FMT_STRING(no_null), 42));
|
||||
#endif
|
||||
#if defined(FMT_USE_STRING_VIEW) && __cplusplus >= 201703L
|
||||
EXPECT_EQ("42", fmt::format(FMT_STRING(std::string_view("{}")), 42));
|
||||
EXPECT_EQ(L"42", fmt::format(FMT_STRING(std::wstring_view(L"{}")), 42));
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(FormatTest, CustomFormatCompileTimeString) {
|
||||
|
Loading…
Reference in New Issue
Block a user