From 79a48344c606074f08563e265333c01ab0a3daf1 Mon Sep 17 00:00:00 2001 From: Alexey Ochapov Date: Sat, 23 Jan 2021 23:43:10 +0300 Subject: [PATCH 1/2] make ranges-test available with C++11, fix problem with some gcc versions --- include/fmt/format.h | 6 +++--- include/fmt/ranges.h | 2 +- test/ranges-test.cc | 39 +++++++++++++++++++++------------------ 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 52e2e7c42c76..30a638ad1acb 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -381,7 +381,7 @@ template inline T* make_checked(T* p, size_t) { return p; } #endif template ::value)> -#if FMT_CLANG_VERSION +#if FMT_CLANG_VERSION >= 307 __attribute__((no_sanitize("undefined"))) #endif inline checked_ptr @@ -940,8 +940,8 @@ template struct FMT_EXTERN_TEMPLATE_API basic_data { static const char reset_color[5]; static const wchar_t wreset_color[5]; static const char signs[]; - static constexpr const char left_padding_shifts[] = {31, 31, 0, 1, 0}; - static constexpr const char right_padding_shifts[] = {0, 31, 0, 1, 0}; + static constexpr const char left_padding_shifts[5] = {31, 31, 0, 1, 0}; + static constexpr const char right_padding_shifts[5] = {0, 31, 0, 1, 0}; // DEPRECATED! These are for ABI compatibility. static const uint32_t zero_or_powers_of_10_32[]; diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index 7b58f4e1b1a4..0ebf96526442 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -368,7 +368,7 @@ template struct tuple_arg_join : detail::view { basic_string_view sep; tuple_arg_join(const std::tuple& t, basic_string_view s) - : tuple{t}, sep{s} {} + : tuple(t), sep{s} {} }; template diff --git a/test/ranges-test.cc b/test/ranges-test.cc index 802f4ab201f7..19538b840fbb 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -11,17 +11,18 @@ #include "fmt/ranges.h" -#include "gtest.h" +#include +#include +#include +#include -// Check if 'if constexpr' is supported. -#if (__cplusplus > 201402L) || \ - (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) +#include "gtest.h" -# include -# include -# include -# include +#if FMT_GCC_VERSION == 0 || FMT_GCC_VERSION >= 601 +# define FMT_ENABLE_C_STYLE_ARRAY_TEST +#endif +#ifdef FMT_ENABLE_C_STYLE_ARRAY_TEST TEST(RangesTest, FormatArray) { int32_t ia[] = {1, 2, 3, 5, 7, 11}; auto iaf = fmt::format("{}", ia); @@ -33,6 +34,7 @@ TEST(RangesTest, Format2dArray) { auto iaf = fmt::format("{}", ia); EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", iaf); } +#endif TEST(RangesTest, FormatVector) { std::vector iv{1, 2, 3, 5, 7, 11}; @@ -51,10 +53,12 @@ TEST(RangesTest, FormatMap) { EXPECT_EQ("{(\"one\", 1), (\"two\", 2)}", fmt::format("{}", simap)); } +#ifdef FMT_ENABLE_C_STYLE_ARRAY_TEST TEST(RangesTest, FormatArrayOfLiterals) { const char* aol[] = {"1234", "abcd"}; EXPECT_EQ("{\"1234\", \"abcd\"}", fmt::format("{}", aol)); } +#endif TEST(RangesTest, FormatPair) { std::pair pa1{42, 1.5f}; @@ -96,15 +100,17 @@ TEST(RangesTest, JoinInitializerList) { struct my_struct { int32_t i; std::string str; // can throw - template decltype(auto) get() const noexcept { - if constexpr (N == 0) - return i; - else if constexpr (N == 1) - return fmt::string_view{str}; + template fmt::enable_if_t get() const noexcept { + return i; + } + template + fmt::enable_if_t get() const noexcept { + return {str}; } }; -template decltype(auto) get(const my_struct& s) noexcept { +template +auto get(const my_struct& s) noexcept -> decltype(s.get()) { return s.get(); } @@ -125,7 +131,7 @@ TEST(RangesTest, FormatStruct) { TEST(RangesTest, FormatTo) { char buf[10]; - auto end = fmt::format_to(buf, "{}", std::vector{1, 2, 3}); + auto end = fmt::format_to(buf, "{}", std::vector{1, 2, 3}); *end = '\0'; EXPECT_STREQ(buf, "{1, 2, 3}"); } @@ -141,9 +147,6 @@ TEST(RangesTest, PathLike) { EXPECT_FALSE((fmt::is_range::value)); } -#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG > - // 201402L && _MSC_VER >= 1910) - #ifdef FMT_USE_STRING_VIEW struct string_like { const char* begin(); From c624fc75367f901bffbe4fcd5da2c93de1b47b80 Mon Sep 17 00:00:00 2001 From: Alexey Ochapov Date: Sun, 24 Jan 2021 01:22:31 +0300 Subject: [PATCH 2/2] potentially fix build for MSVC 19.10, a bit reorganizing in test --- test/ranges-test.cc | 155 +++++++++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 74 deletions(-) diff --git a/test/ranges-test.cc b/test/ranges-test.cc index 19538b840fbb..30ed97f21233 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -18,11 +18,16 @@ #include "gtest.h" -#if FMT_GCC_VERSION == 0 || FMT_GCC_VERSION >= 601 -# define FMT_ENABLE_C_STYLE_ARRAY_TEST +#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 601 +# define FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY #endif -#ifdef FMT_ENABLE_C_STYLE_ARRAY_TEST +#if !FMT_MSC_VER || FMT_MSC_VER > 1910 +# define FMT_RANGES_TEST_ENABLE_JOIN +# define FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT +#endif + +#ifdef FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY TEST(RangesTest, FormatArray) { int32_t ia[] = {1, 2, 3, 5, 7, 11}; auto iaf = fmt::format("{}", ia); @@ -34,7 +39,12 @@ TEST(RangesTest, Format2dArray) { auto iaf = fmt::format("{}", ia); EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", iaf); } -#endif + +TEST(RangesTest, FormatArrayOfLiterals) { + const char* aol[] = {"1234", "abcd"}; + EXPECT_EQ("{\"1234\", \"abcd\"}", fmt::format("{}", aol)); +} +#endif // FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY TEST(RangesTest, FormatVector) { std::vector iv{1, 2, 3, 5, 7, 11}; @@ -53,13 +63,6 @@ TEST(RangesTest, FormatMap) { EXPECT_EQ("{(\"one\", 1), (\"two\", 2)}", fmt::format("{}", simap)); } -#ifdef FMT_ENABLE_C_STYLE_ARRAY_TEST -TEST(RangesTest, FormatArrayOfLiterals) { - const char* aol[] = {"1234", "abcd"}; - EXPECT_EQ("{\"1234\", \"abcd\"}", fmt::format("{}", aol)); -} -#endif - TEST(RangesTest, FormatPair) { std::pair pa1{42, 1.5f}; EXPECT_EQ("(42, 1.5)", fmt::format("{}", pa1)); @@ -72,31 +75,7 @@ TEST(RangesTest, FormatTuple) { EXPECT_EQ("()", fmt::format("{}", std::tuple<>())); } -TEST(RangesTest, JoinTuple) { - // Value tuple args - std::tuple t1 = std::make_tuple('a', 1, 2.0f); - EXPECT_EQ("(a, 1, 2)", fmt::format("({})", fmt::join(t1, ", "))); - - // Testing lvalue tuple args - int x = 4; - std::tuple t2{'b', x}; - EXPECT_EQ("b + 4", fmt::format("{}", fmt::join(t2, " + "))); - - // Empty tuple - std::tuple<> t3; - EXPECT_EQ("", fmt::format("{}", fmt::join(t3, "|"))); - - // Single element tuple - std::tuple t4{4.0f}; - EXPECT_EQ("4", fmt::format("{}", fmt::join(t4, "/"))); -} - -TEST(RangesTest, JoinInitializerList) { - EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join({1, 2, 3}, ", "))); - EXPECT_EQ("fmt rocks !", - fmt::format("{}", fmt::join({"fmt", "rocks", "!"}, " "))); -} - +#ifdef FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT struct my_struct { int32_t i; std::string str; // can throw @@ -128,6 +107,7 @@ TEST(RangesTest, FormatStruct) { my_struct mst{13, "my struct"}; EXPECT_EQ("(13, \"my struct\")", fmt::format("{}", mst)); } +#endif // FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT TEST(RangesTest, FormatTo) { char buf[10]; @@ -160,23 +140,6 @@ TEST(RangesTest, FormatStringLike) { } #endif // FMT_USE_STRING_VIEW -struct zstring_sentinel {}; - -bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; } -bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; } - -struct zstring { - const char* p; - const char* begin() const { return p; } - zstring_sentinel end() const { return {}; } -}; - -TEST(RangesTest, JoinSentinel) { - zstring hello{"hello"}; - EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello)); - EXPECT_EQ("h_e_l_l_o", fmt::format("{}", fmt::join(hello, "_"))); -} - // A range that provides non-const only begin()/end() to test fmt::join handles // that // @@ -215,27 +178,6 @@ template class noncopyable_range { const_iterator end() const { return vec.end(); } }; -TEST(RangesTest, JoinRange) { - noncopyable_range w(3u, 0); - EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(w, ","))); - EXPECT_EQ("0,0,0", - fmt::format("{}", fmt::join(noncopyable_range(3u, 0), ","))); - - non_const_only_range x(3u, 0); - EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(x, ","))); - EXPECT_EQ( - "0,0,0", - fmt::format("{}", fmt::join(non_const_only_range(3u, 0), ","))); - - std::vector y(3u, 0); - EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(y, ","))); - EXPECT_EQ("0,0,0", - fmt::format("{}", fmt::join(std::vector(3u, 0), ","))); - - const std::vector z(3u, 0); - EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ","))); -} - TEST(RangesTest, Range) { noncopyable_range w(3u, 0); EXPECT_EQ("{0, 0, 0}", fmt::format("{}", w)); @@ -261,3 +203,68 @@ TEST(RangesTest, UnformattableRange) { fmt::format_context>::value)); } #endif + +#ifdef FMT_RANGES_TEST_ENABLE_JOIN +TEST(RangesTest, JoinTuple) { + // Value tuple args + std::tuple t1 = std::make_tuple('a', 1, 2.0f); + EXPECT_EQ("(a, 1, 2)", fmt::format("({})", fmt::join(t1, ", "))); + + // Testing lvalue tuple args + int x = 4; + std::tuple t2{'b', x}; + EXPECT_EQ("b + 4", fmt::format("{}", fmt::join(t2, " + "))); + + // Empty tuple + std::tuple<> t3; + EXPECT_EQ("", fmt::format("{}", fmt::join(t3, "|"))); + + // Single element tuple + std::tuple t4{4.0f}; + EXPECT_EQ("4", fmt::format("{}", fmt::join(t4, "/"))); +} + +TEST(RangesTest, JoinInitializerList) { + EXPECT_EQ("1, 2, 3", fmt::format("{}", fmt::join({1, 2, 3}, ", "))); + EXPECT_EQ("fmt rocks !", + fmt::format("{}", fmt::join({"fmt", "rocks", "!"}, " "))); +} + +struct zstring_sentinel {}; + +bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; } +bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; } + +struct zstring { + const char* p; + const char* begin() const { return p; } + zstring_sentinel end() const { return {}; } +}; + +TEST(RangesTest, JoinSentinel) { + zstring hello{"hello"}; + EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello)); + EXPECT_EQ("h_e_l_l_o", fmt::format("{}", fmt::join(hello, "_"))); +} + +TEST(RangesTest, JoinRange) { + noncopyable_range w(3u, 0); + EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(w, ","))); + EXPECT_EQ("0,0,0", + fmt::format("{}", fmt::join(noncopyable_range(3u, 0), ","))); + + non_const_only_range x(3u, 0); + EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(x, ","))); + EXPECT_EQ( + "0,0,0", + fmt::format("{}", fmt::join(non_const_only_range(3u, 0), ","))); + + std::vector y(3u, 0); + EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(y, ","))); + EXPECT_EQ("0,0,0", + fmt::format("{}", fmt::join(std::vector(3u, 0), ","))); + + const std::vector z(3u, 0); + EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ","))); +} +#endif // FMT_RANGES_TEST_ENABLE_JOIN \ No newline at end of file