diff --git a/include/fmt/core.h b/include/fmt/core.h index 6ab2df08..b2c8360c 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -146,20 +146,23 @@ #if (FMT_HAS_INCLUDE() && __cplusplus > 201402L) || \ (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) # include -namespace fmt { using std::basic_string_view; } +# define FMT_USE_STD_STRING_VIEW // std::experimental::basic_string_view::remove_prefix isn't constexpr until // gcc 7.3. #elif (FMT_HAS_INCLUDE() && \ (FMT_GCC_VERSION == 0 || FMT_GCC_VERSION >= 730) && \ __cplusplus >= 201402L) # include -namespace fmt { using std::experimental::basic_string_view; } -#else +# define FMT_USE_EXPERIMENTAL_STRING_VIEW +#endif + namespace fmt { /** \rst An implementation of ``std::basic_string_view`` for pre-C++17. It provides a - subset of the API. + subset of the API. fmt::basic_string_view is used for format strings even if + std::string_view is available to prevent issues when a library is compiled + with different -std option than the client code (which is not recommended). \endrst */ template @@ -172,6 +175,18 @@ class basic_string_view { typedef Char char_type; typedef const Char *iterator; + // Standard basic_string_view type. +#if defined(FMT_USE_STD_STRING_VIEW) + typedef std::basic_string_view type; +#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) + typedef std::experimental::basic_string_view type; +#else + struct type { + const char *data() const { return FMT_NULL; } + size_t size() const { return 0; }; + }; +#endif + FMT_CONSTEXPR basic_string_view() FMT_NOEXCEPT : data_(FMT_NULL), size_(0) {} /** Constructs a string reference object from a C string and a size. */ @@ -197,6 +212,9 @@ class basic_string_view { const std::basic_string &s) FMT_NOEXCEPT : data_(s.c_str()), size_(s.size()) {} + FMT_CONSTEXPR basic_string_view(type s) FMT_NOEXCEPT + : data_(s.data()), size_(s.size()) {} + /** Returns a pointer to the string data. */ const Char *data() const { return data_; } @@ -239,10 +257,7 @@ class basic_string_view { return lhs.compare(rhs) >= 0; } }; -} // namespace fmt -#endif -namespace fmt { typedef basic_string_view string_view; typedef basic_string_view wstring_view; @@ -572,6 +587,9 @@ FMT_MAKE_VALUE(cstring_type, unsigned char*, const unsigned char*) FMT_MAKE_VALUE(cstring_type, const unsigned char*, const unsigned char*) FMT_MAKE_VALUE(string_type, basic_string_view, basic_string_view) +FMT_MAKE_VALUE(string_type, + typename basic_string_view::type, + basic_string_view) FMT_MAKE_VALUE(string_type, const std::basic_string&, basic_string_view) FMT_MAKE_VALUE(pointer_type, void*, const void*) diff --git a/test/format-test.cc b/test/format-test.cc index 4555e479..f3a961f2 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1213,6 +1213,12 @@ TEST(FormatterTest, FormatStringView) { EXPECT_EQ("test", format("{0}", string_view("test"))); } +#ifdef FMT_USE_STD_STRING_VIEW +TEST(FormatterTest, FormatStringView) { + EXPECT_EQ("test", format("{0}", std::string_view("test"))); +} +#endif + struct ConvertibleToString { std::string s; ConvertibleToString() : s("foo") {}