-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make ranges-test available with C++11 #2114
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -381,7 +381,7 @@ template <typename T> inline T* make_checked(T* p, size_t) { return p; } | |
#endif | ||
|
||
template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)> | ||
#if FMT_CLANG_VERSION | ||
#if FMT_CLANG_VERSION >= 307 | ||
__attribute__((no_sanitize("undefined"))) | ||
#endif | ||
inline checked_ptr<typename Container::value_type> | ||
|
@@ -940,8 +940,8 @@ template <typename T = void> 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}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some GCC versions fail to determine the size of this array - https://godbolt.org/z/KbhMGb There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a gcc bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66921. |
||
|
||
// DEPRECATED! These are for ABI compatibility. | ||
static const uint32_t zero_or_powers_of_10_32[]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -368,7 +368,7 @@ template <typename Char, typename... T> struct tuple_arg_join : detail::view { | |
basic_string_view<Char> sep; | ||
|
||
tuple_arg_join(const std::tuple<T...>& t, basic_string_view<Char> s) | ||
: tuple{t}, sep{s} {} | ||
: tuple(t), sep{s} {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GCC 4.8 fails to initialize tuple ref by braces - https://godbolt.org/z/qxq5eK |
||
}; | ||
|
||
template <typename Char, typename... T> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,17 +11,23 @@ | |
|
||
#include "fmt/ranges.h" | ||
|
||
#include <array> | ||
#include <map> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "gtest.h" | ||
|
||
// Check if 'if constexpr' is supported. | ||
#if (__cplusplus > 201402L) || \ | ||
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) | ||
#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 601 | ||
# define FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY | ||
#endif | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's strange but looks like GCC <6 unable to pass C-style array correctly, so {fmt} is unable right now to format them - https://godbolt.org/z/MYYf6W |
||
|
||
# include <array> | ||
# include <map> | ||
# include <string> | ||
# include <vector> | ||
#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,6 +40,12 @@ TEST(RangesTest, Format2dArray) { | |
EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", iaf); | ||
} | ||
|
||
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<int32_t> iv{1, 2, 3, 5, 7, 11}; | ||
auto ivf = fmt::format("{}", iv); | ||
|
@@ -51,11 +63,6 @@ TEST(RangesTest, FormatMap) { | |
EXPECT_EQ("{(\"one\", 1), (\"two\", 2)}", fmt::format("{}", simap)); | ||
} | ||
|
||
TEST(RangesTest, FormatArrayOfLiterals) { | ||
const char* aol[] = {"1234", "abcd"}; | ||
EXPECT_EQ("{\"1234\", \"abcd\"}", fmt::format("{}", aol)); | ||
} | ||
|
||
TEST(RangesTest, FormatPair) { | ||
std::pair<int64_t, float> pa1{42, 1.5f}; | ||
EXPECT_EQ("(42, 1.5)", fmt::format("{}", pa1)); | ||
|
@@ -68,43 +75,21 @@ TEST(RangesTest, FormatTuple) { | |
EXPECT_EQ("()", fmt::format("{}", std::tuple<>())); | ||
} | ||
|
||
TEST(RangesTest, JoinTuple) { | ||
// Value tuple args | ||
std::tuple<char, int, float> 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<char, int&> 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<float> 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 | ||
template <size_t N> decltype(auto) get() const noexcept { | ||
if constexpr (N == 0) | ||
return i; | ||
else if constexpr (N == 1) | ||
return fmt::string_view{str}; | ||
template <size_t N> fmt::enable_if_t<N == 0, int32_t> get() const noexcept { | ||
return i; | ||
} | ||
template <size_t N> | ||
fmt::enable_if_t<N == 1, fmt::string_view> get() const noexcept { | ||
return {str}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No C++14 |
||
} | ||
}; | ||
|
||
template <size_t N> decltype(auto) get(const my_struct& s) noexcept { | ||
template <size_t N> | ||
auto get(const my_struct& s) noexcept -> decltype(s.get<N>()) { | ||
return s.get<N>(); | ||
} | ||
|
||
|
@@ -122,10 +107,11 @@ 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]; | ||
auto end = fmt::format_to(buf, "{}", std::vector{1, 2, 3}); | ||
auto end = fmt::format_to(buf, "{}", std::vector<int>{1, 2, 3}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No C++17 template deduction |
||
*end = '\0'; | ||
EXPECT_STREQ(buf, "{1, 2, 3}"); | ||
} | ||
|
@@ -141,9 +127,6 @@ TEST(RangesTest, PathLike) { | |
EXPECT_FALSE((fmt::is_range<path_like, char>::value)); | ||
} | ||
|
||
#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG > | ||
// 201402L && _MSC_VER >= 1910) | ||
|
||
#ifdef FMT_USE_STRING_VIEW | ||
struct string_like { | ||
const char* begin(); | ||
|
@@ -157,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 | ||
// | ||
|
@@ -212,27 +178,6 @@ template <typename T> class noncopyable_range { | |
const_iterator end() const { return vec.end(); } | ||
}; | ||
|
||
TEST(RangesTest, JoinRange) { | ||
noncopyable_range<int> w(3u, 0); | ||
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(w, ","))); | ||
EXPECT_EQ("0,0,0", | ||
fmt::format("{}", fmt::join(noncopyable_range<int>(3u, 0), ","))); | ||
|
||
non_const_only_range<int> 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<int>(3u, 0), ","))); | ||
|
||
std::vector<int> y(3u, 0); | ||
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(y, ","))); | ||
EXPECT_EQ("0,0,0", | ||
fmt::format("{}", fmt::join(std::vector<int>(3u, 0), ","))); | ||
|
||
const std::vector<int> z(3u, 0); | ||
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ","))); | ||
} | ||
|
||
TEST(RangesTest, Range) { | ||
noncopyable_range<int> w(3u, 0); | ||
EXPECT_EQ("{0, 0, 0}", fmt::format("{}", w)); | ||
|
@@ -258,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<char, int, float> 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<char, int&> 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<float> 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<int> w(3u, 0); | ||
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(w, ","))); | ||
EXPECT_EQ("0,0,0", | ||
fmt::format("{}", fmt::join(noncopyable_range<int>(3u, 0), ","))); | ||
|
||
non_const_only_range<int> 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<int>(3u, 0), ","))); | ||
|
||
std::vector<int> y(3u, 0); | ||
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(y, ","))); | ||
EXPECT_EQ("0,0,0", | ||
fmt::format("{}", fmt::join(std::vector<int>(3u, 0), ","))); | ||
|
||
const std::vector<int> z(3u, 0); | ||
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ","))); | ||
} | ||
#endif // FMT_RANGES_TEST_ENABLE_JOIN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like there is no
no_sanitize
attribute prior to Clang 3.7Maybe a bit unrelated to this PR, but it was found while I was working on it