diff --git a/doc/api.rst b/doc/api.rst index ed2a1e4e..8a226758 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -180,10 +180,6 @@ You can also write a formatter for a hierarchy of classes:: fmt::print("{}", a); // prints "B" } -This section shows how to define a custom format function for a user-defined -type. The next section describes how to get ``fmt`` to use a conventional stream -output ``operator<<`` when one is defined for a user-defined type. - Output Iterator Support ----------------------- @@ -214,6 +210,10 @@ Utilities .. doxygenfunction:: fmt::to_string_view(basic_string_view) +.. doxygenfunction:: fmt::join(const Range&, string_view) + +.. doxygenfunction:: fmt::join(It, It, string_view) + .. doxygenclass:: fmt::basic_memory_buffer :protected-members: :members: diff --git a/include/fmt/format.h b/include/fmt/format.h index 32317c77..ca56fab0 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -162,13 +162,6 @@ FMT_END_NAMESPACE # endif #endif -#if FMT_HAS_GXX_CXX11 || FMT_HAS_FEATURE(cxx_trailing_return) || \ - FMT_MSC_VER >= 1600 -# define FMT_USE_TRAILING_RETURN 1 -#else -# define FMT_USE_TRAILING_RETURN 0 -#endif - #ifdef FMT_USE_INT128 // Do nothing. #elif defined(__SIZEOF_INT128__) @@ -291,6 +284,12 @@ FMT_CONSTEXPR T* end(T (&array)[N]) FMT_NOEXCEPT { return array + N; } +// An implementation of iterator_t for pre-C++20 compilers such as gcc 4. +template +struct iterator_t { + typedef decltype(internal::begin(internal::declval())) type; +}; + // For std::result_of in gcc 4.4. template struct function { template struct result { typedef Result type; }; @@ -3302,6 +3301,10 @@ struct formatter, Char> } }; +/** + Returns an object that formats the iterator range `[begin, end)` with elements + separated by `sep`. + */ template arg_join join(It begin, It end, string_view sep) { return arg_join(begin, end, sep); @@ -3312,17 +3315,28 @@ arg_join join(It begin, It end, wstring_view sep) { return arg_join(begin, end, sep); } -// The following causes ICE in gcc 4.4. -#if FMT_USE_TRAILING_RETURN && (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 405) +// gcc 4.4 on join: internal compiler error: in tsubst_copy, at cp/pt.c:10122 +#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 405 +/** + \rst + Returns an object that formats `range` with elements separated by `sep`. + + **Example**:: + + std::vector v = {1, 2, 3}; + fmt::print("{}", fmt::join(v, ", ")); + // Output: "1, 2, 3" + \endrst + */ template -auto join(const Range& range, string_view sep) - -> arg_join { +arg_join::type, char> + join(const Range& range, string_view sep) { return join(internal::begin(range), internal::end(range), sep); } template -auto join(const Range& range, wstring_view sep) - -> arg_join { +arg_join::type, wchar_t> + join(const Range& range, wstring_view sep) { return join(internal::begin(range), internal::end(range), sep); } #endif diff --git a/test/format-test.cc b/test/format-test.cc index 14a7f87a..0b4b2176 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1793,7 +1793,7 @@ TEST(FormatTest, JoinArg) { EXPECT_EQ(format("{}, {}", v3[0], v3[1]), format("{}", join(v3, v3 + 2, ", "))); -#if FMT_USE_TRAILING_RETURN && (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 405) +#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 405 EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, ", "))); EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", join(v2, ", "))); #endif