diff --git a/include/fmt/core.h b/include/fmt/core.h index 72fc739d..5ff02fa4 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -187,25 +187,34 @@ # define FMT_ASSERT(condition, message) assert((condition) && message) #endif -// libc++ supports string_view in pre-c++17. -#if (FMT_HAS_INCLUDE() && \ - (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \ - (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) -# include -# define FMT_STRING_VIEW std::basic_string_view -#elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L -# include -# define FMT_STRING_VIEW std::experimental::basic_string_view -#endif - // An enable_if helper to be used in template parameters. enable_if in template // parameters results in much shorter symbols: https://godbolt.org/z/sWw4vP. #define FMT_ENABLE_IF_T(...) typename std::enable_if<(__VA_ARGS__), int>::type #define FMT_ENABLE_IF(...) FMT_ENABLE_IF_T(__VA_ARGS__) = 0 +// libc++ supports string_view in pre-c++17. +#if (FMT_HAS_INCLUDE() && \ + (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) +# include +# define FMT_USE_STRING_VIEW +#elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L +# include +# define FMT_USE_EXPERIMENTAL_STRING_VIEW +#endif + FMT_BEGIN_NAMESPACE namespace internal { +#if defined(FMT_USE_STRING_VIEW) +template using std_string_view = std::basic_string_view; +#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) +template +using std_string_view = std::experimental::basic_string_view; +#else +template struct std_string_view {}; +#endif + template struct result_of; #if (__cplusplus >= 201703L || \ @@ -396,11 +405,11 @@ template class basic_string_view { FMT_NOEXCEPT : data_(s.data()), size_(s.size()) {} -#ifdef FMT_STRING_VIEW - FMT_CONSTEXPR basic_string_view(FMT_STRING_VIEW s) FMT_NOEXCEPT - : data_(s.data()), - size_(s.size()) {} -#endif + template < + typename S, + FMT_ENABLE_IF(std::is_same>::value)> + FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()), + size_(s.size()) {} /** Returns a pointer to the string data. */ FMT_CONSTEXPR const Char* data() const { return data_; } @@ -486,12 +495,12 @@ inline basic_string_view to_string_view(const Char* s) { return s; } -#ifdef FMT_STRING_VIEW -template -inline basic_string_view to_string_view(FMT_STRING_VIEW s) { +template >::value)> +inline basic_string_view to_string_view( + internal::std_string_view s) { return s; } -#endif // A base class for compile-time strings. It is defined in the fmt namespace to // make formatting functions visible via ADL, e.g. format(fmt("{}"), 42). diff --git a/test/core-test.cc b/test/core-test.cc index 8cd3b047..5f210b8d 100644 --- a/test/core-test.cc +++ b/test/core-test.cc @@ -475,9 +475,7 @@ class QString { QString(const wchar_t* s) : s_(std::make_shared(s)) {} const wchar_t* utf16() const FMT_NOEXCEPT { return s_->data(); } int size() const FMT_NOEXCEPT { return static_cast(s_->size()); } -#ifdef FMT_STRING_VIEW - operator FMT_STRING_VIEW() const FMT_NOEXCEPT { return *s_; } -#endif + private: std::shared_ptr s_; }; @@ -499,21 +497,21 @@ struct derived_from_string_view : fmt::basic_string_view {}; } // namespace TYPED_TEST(IsStringTest, IsString) { - EXPECT_TRUE((fmt::internal::is_string::value)); - EXPECT_TRUE((fmt::internal::is_string::value)); - EXPECT_TRUE((fmt::internal::is_string::value)); - EXPECT_TRUE((fmt::internal::is_string::value)); - EXPECT_TRUE((fmt::internal::is_string>::value)); + EXPECT_TRUE(fmt::internal::is_string::value); + EXPECT_TRUE(fmt::internal::is_string::value); + EXPECT_TRUE(fmt::internal::is_string::value); + EXPECT_TRUE(fmt::internal::is_string::value); + EXPECT_TRUE(fmt::internal::is_string>::value); EXPECT_TRUE( - (fmt::internal::is_string>::value)); + fmt::internal::is_string>::value); EXPECT_TRUE( - (fmt::internal::is_string>::value)); -#ifdef FMT_STRING_VIEW - EXPECT_TRUE((fmt::internal::is_string>::value)); -#endif - EXPECT_TRUE((fmt::internal::is_string>::value)); - EXPECT_FALSE((fmt::internal::is_string::value)); - EXPECT_TRUE((fmt::internal::is_string::value)); + fmt::internal::is_string>::value); + using string_view = fmt::internal::std_string_view; + EXPECT_TRUE(std::is_empty::value != + fmt::internal::is_string::value); + EXPECT_TRUE(fmt::internal::is_string>::value); + EXPECT_FALSE(fmt::internal::is_string::value); + EXPECT_TRUE(fmt::internal::is_string::value); } TEST(CoreTest, Format) {