Merge branch 'master' of https://github.com/fmtlib/fmt
# Conflicts resolved: # include/fmt/ranges.h # test/ranges-test.cc
This commit is contained in:
commit
b607de85be
@ -96,7 +96,7 @@ endfunction()
|
||||
|
||||
# Define the fmt library, its includes and the needed defines.
|
||||
add_headers(FMT_HEADERS core.h format.h format-inl.h locale.h ostream.h printf.h
|
||||
time.h)
|
||||
time.h ranges.h)
|
||||
set(FMT_SOURCES src/format.cc)
|
||||
if (HAVE_OPEN)
|
||||
add_headers(FMT_HEADERS posix.h)
|
||||
|
||||
162
ChangeLog.rst
162
ChangeLog.rst
@ -1,18 +1,21 @@
|
||||
5.0.0 - TBD
|
||||
-----------
|
||||
|
||||
* Added a requirement for compiler support for variadic templates and dropped
|
||||
``FMT_VARIADIC_*`` emulation macros. Variadic templates are available since
|
||||
GCC 4.4, Clang 2.9 and MSVC 18.0 (2013). For older compilers use `version 4.x
|
||||
* Added a requirement for partial C++11 support, most importantly variadic
|
||||
templates and type traits, and dropped ``FMT_VARIADIC_*`` emulation macros.
|
||||
Variadic templates are available since GCC 4.4, Clang 2.9 and MSVC 18.0 (2013).
|
||||
For older compilers use {fmt} `version 4.x
|
||||
<https://github.com/fmtlib/fmt/releases/tag/4.1.0>`_ which continues to be
|
||||
maintained.
|
||||
maintained and works with C++98 compilers.
|
||||
|
||||
* Renamed symbols to follow standard C++ naming conventions and proposed a subset
|
||||
of the library for standardization in `P0645R2 Text Formatting
|
||||
<https://wg21.link/P0645>`_.
|
||||
|
||||
* Swparated format string parsing and formatting in the extension API to enable
|
||||
compile-time format-string processing. For example
|
||||
* Implemented ``constexpr`` parsing of format strings.
|
||||
|
||||
* Separated format string parsing and formatting in the extension API to enable
|
||||
compile-time format string processing. For example
|
||||
|
||||
.. code:: c++
|
||||
|
||||
@ -26,8 +29,7 @@
|
||||
spec = *it;
|
||||
if (spec != 'd' && spec != 's')
|
||||
throw format_error("invalid specifier");
|
||||
++it;
|
||||
return it;
|
||||
return ++it;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
@ -41,15 +43,48 @@
|
||||
};
|
||||
}
|
||||
|
||||
std::string s = fmt::format(fmt("{:x}"), S());
|
||||
std::string s = format(fmt("{:x}"), S());
|
||||
|
||||
will give a compile-time error due to invalid format specifier (`godbolt
|
||||
<https://godbolt.org/g/9s4kNB>`_)::
|
||||
<https://godbolt.org/g/ywhrPp>`_)::
|
||||
|
||||
...
|
||||
<source>:12:45: error: expression '<throw-expression>' is not a constant expression
|
||||
throw format_error("invalid specifier");
|
||||
|
||||
* Added `iterator support
|
||||
<http://fmtlib.net/dev/api.html#output-iterator-support>`_:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <vector>
|
||||
#include <fmt/format.h>
|
||||
|
||||
std::vector<char> out;
|
||||
fmt::format_to(std::back_inserter(out), "{}", 42);
|
||||
|
||||
* Added the `formatted_size
|
||||
<http://fmtlib.net/dev/api.html#output-iterator-support>`_ function for
|
||||
computing output size:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
auto size = fmt::formatted_size("{}", 12345); // size == 5
|
||||
|
||||
* Improved compile times by reducing dependencies on standard headers and
|
||||
providing a lightweight `core API <http://fmtlib.net/dev/api.html#core-api>`_:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
fmt::print("The answer is {}.", 42);
|
||||
|
||||
See `Compile time and code bloat
|
||||
<https://github.com/fmtlib/fmt#compile-time-and-code-bloat>`_.
|
||||
|
||||
* Added the `make_format_args
|
||||
<http://fmtlib.net/dev/api.html#_CPPv2N3fmt16make_format_argsEDpRK4Args>`_
|
||||
function for capturing formatting arguments:
|
||||
@ -80,30 +115,45 @@
|
||||
in the format API and provided ``fmt::string_view`` which implements a subset
|
||||
of ``std::string_view`` API for pre-C++17 systems.
|
||||
|
||||
* Added support for ``std::experimental::string_view``
|
||||
(`#607 <https://github.com/fmtlib/fmt/pull/607>`_):
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <experimental/string_view>
|
||||
|
||||
fmt::print("{}", std::experimental::string_view("foo"));
|
||||
|
||||
Thanks `@virgiliofornazin (Virgilio Alexandre Fornazin)
|
||||
<https://github.com/virgiliofornazin>`_.
|
||||
|
||||
* Allowed mixing named and automatic arguments:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::format("{} {two}", 1, fmt::arg("two", 2));
|
||||
|
||||
* Removed the write API in favor of the `format API
|
||||
<http://fmtlib.net/dev/api.html#format-api>`_ with compile-time handling of
|
||||
format strings.
|
||||
|
||||
* Added a section on `formatting user-defined types
|
||||
<http://fmtlib.net/dev/api.html#formatting-user-defined-types>`_ to the docs
|
||||
(`#393 <https://github.com/fmtlib/fmt/pull/393>`_).
|
||||
Thanks `@pwm1234 (Phil) <https://github.com/pwm1234>`_.
|
||||
* Disallowed formatting of multibyte strings into a wide character target
|
||||
(`#606 <https://github.com/fmtlib/fmt/pull/606>`_).
|
||||
|
||||
* Added a section describing `the use of header-only target with CMake
|
||||
<http://fmtlib.net/dev/usage.html#header-only-usage-with-cmake>`_ to the docs
|
||||
(`#515 <https://github.com/fmtlib/fmt/pull/515>`_).
|
||||
Thanks `@ibell (Ian Bell) <https://github.com/ibell>`_.
|
||||
|
||||
* Implemented thread-safe time formatting (
|
||||
`#395 <https://github.com/fmtlib/fmt/issues/395>`_,
|
||||
`#396 <https://github.com/fmtlib/fmt/pull/396>`_).
|
||||
Thanks `@codicodi <https://github.com/codicodi>`_.
|
||||
* Added a `note about errno <http://fmtlib.net/latest/index.html#safety>`_ to the
|
||||
documentation (
|
||||
`#614 <https://github.com/fmtlib/fmt/issues/614>`_,
|
||||
`#617 <https://github.com/fmtlib/fmt/pull/617>`_).
|
||||
Thanks `@mihaitodor (Mihai Todor) <https://github.com/mihaitodor>`_.
|
||||
|
||||
* Implemented more efficient handling of large number of format arguments.
|
||||
|
||||
* Added a version macro ``FMT_VERSION``
|
||||
(`#411 <https://github.com/fmtlib/fmt/issues/411>`_).
|
||||
|
||||
* Removed unnecessary ``fmt/`` prefix in includes
|
||||
(`#397 <https://github.com/fmtlib/fmt/pull/397>`_).
|
||||
Thanks `@chronoxor (Ivan Shynkarenka) <https://github.com/chronoxor>`_.
|
||||
@ -111,75 +161,17 @@
|
||||
* Renamed ``CHAR_WIDTH`` to ``CHAR_SIZE`` to avoid collision with ISO/IEC TS
|
||||
18661-1:2014 macro.
|
||||
|
||||
* Replaced literal 0 with ``nullptr`` in pointer contexts
|
||||
(`#409 <https://github.com/fmtlib/fmt/pull/409>`_).
|
||||
Thanks `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
|
||||
|
||||
* Added ``std::basic_string`` allocator support to ``fmt::string_view``
|
||||
(`#441 <https://github.com/fmtlib/fmt/pull/441>`_).
|
||||
Thanks `@glebov-andrey (Andrey Glebov) <https://github.com/glebov-andrey>`_.
|
||||
|
||||
* Stopped exporting the ``-std=c++11`` flag from the ``fmt`` target
|
||||
(`#445 <https://github.com/fmtlib/fmt/pull/445>`_).
|
||||
Thanks `@EricWF (Eric) <https://github.com/EricWF>`_.
|
||||
|
||||
* Made ``%s`` a generic format specifier that works with any argument type in
|
||||
``fmt::printf`` (`#453 <https://github.com/fmtlib/fmt/pull/453>`_).
|
||||
Thanks `@mojoBrendan <https://github.com/mojoBrendan>`_:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::printf("%s", 42);
|
||||
|
||||
* Placed CMake imported targets in the `fmt` namespace (
|
||||
`#511 <https://github.com/fmtlib/fmt/pull/511>`_,
|
||||
`#513 <https://github.com/fmtlib/fmt/pull/513>`_).
|
||||
Thanks `@bjoernthiel (Bjoern Thiel) <https://github.com/bjoernthiel>`_ and
|
||||
`@niosHD (Mario Werner) <https://github.com/niosHD>`_.
|
||||
|
||||
* Fixed minimal supported library subset (
|
||||
`#418 <https://github.com/fmtlib/fmt/issues/418>`_,
|
||||
`#419 <https://github.com/fmtlib/fmt/pull/419>`_,
|
||||
`#420 <https://github.com/fmtlib/fmt/pull/420>`_).
|
||||
Thanks `@alabuzhev (Alex Alabuzhev) <https://github.com/alabuzhev>`_.
|
||||
|
||||
* Fixed compilation on Android
|
||||
(`#381 <https://github.com/fmtlib/fmt/pull/381>`_).
|
||||
Thanks `@hghwng (Hugh Wang) <https://github.com/hghwng>`_.
|
||||
|
||||
* Fixed compilation with ``-fno-exceptions`` (
|
||||
`#402 <https://github.com/fmtlib/fmt/pull/402>`_,
|
||||
`#405 <https://github.com/fmtlib/fmt/pull/405>`_).
|
||||
Thanks `@JanHellwig (Jan Hellwig) <https://github.com/JanHellwig>`_.
|
||||
|
||||
* Fixed compilation as a shared library with Clang
|
||||
(`#413 <https://github.com/fmtlib/fmt/pull/413>`_).
|
||||
Thanks `@foonathan (Jonathan Müller) <https://github.com/foonathan>`_.
|
||||
|
||||
* Fixed test compilation on FreeBSD
|
||||
(`#433 <https://github.com/fmtlib/fmt/issues/433>`_).
|
||||
Thanks `@WscriChy <https://github.com/WscriChy>`_.
|
||||
|
||||
* Fixed a name conflict with Xlib
|
||||
(`#483 <https://github.com/fmtlib/fmt/issues/483>`_).
|
||||
|
||||
* Fixed signbit detection (`#423 <https://github.com/fmtlib/fmt/pull/423>`_).
|
||||
|
||||
* Fixed missing intrinsic when included from C++/CLI
|
||||
(`#457 <https://github.com/fmtlib/fmt/pull/457>`_).
|
||||
Thanks `@calumr (Calum Robinson) <https://github.com/calumr>`_.
|
||||
|
||||
* Fixed Android not being detected with NDK 13b toolchain
|
||||
(`#458 <https://github.com/fmtlib/fmt/pull/458>`_).
|
||||
Thanks `@Gachapen (Magnus Bjerke Vik) <https://github.com/Gachapen>`_.
|
||||
* Fixed a name conflict with the macro ``CHAR_WIDTH`` in glibc
|
||||
(`#616 <https://github.com/fmtlib/fmt/pull/616>`_).
|
||||
Thanks `@aroig (Abdó Roig-Maranges) <https://github.com/aroig>`_.
|
||||
|
||||
* Added ``SOURCELINK_SUFFIX`` for compatibility with Sphinx 1.5
|
||||
(`#497 <https://github.com/fmtlib/fmt/pull/497>`_).
|
||||
Thanks `@ginggs (Graham Inggs) <https://github.com/ginggs>`_.
|
||||
|
||||
* Added ``FMT_API`` declarations where needed for building a DLL
|
||||
(`#469 <https://github.com/fmtlib/fmt/pull/469>`_).
|
||||
Thanks `@richardeakin (Richard Eakin) <https://github.com/richardeakin>`_.
|
||||
* Added a missing ``inline`` in the header-only mode
|
||||
(`#626 <https://github.com/fmtlib/fmt/pull/626>`_).
|
||||
Thanks `@aroig (Abdó Roig-Maranges) <https://github.com/aroig>`_.
|
||||
|
||||
4.1.0 - 2017-12-20
|
||||
------------------
|
||||
|
||||
@ -151,6 +151,8 @@ The following user-defined literals are defined in ``fmt/format.h``.
|
||||
Utilities
|
||||
---------
|
||||
|
||||
.. doxygenfunction:: fmt::formatted_size(string_view, const Args&...)
|
||||
|
||||
.. doxygenfunction:: fmt::to_string(const T&)
|
||||
|
||||
.. doxygenfunction:: fmt::to_wstring(const T&)
|
||||
|
||||
@ -33,13 +33,13 @@ in Python:
|
||||
fmt::format("The answer is {}", 42);
|
||||
|
||||
The ``fmt::format`` function returns a string "The answer is 42". You can use
|
||||
``fmt::MemoryWriter`` to avoid constructing ``std::string``:
|
||||
``fmt::memory_buffer`` to avoid constructing ``std::string``:
|
||||
|
||||
.. code:: c++
|
||||
|
||||
fmt::MemoryWriter w;
|
||||
w.write("Look, a {} string", 'C');
|
||||
w.c_str(); // returns a C string (const char*)
|
||||
fmt::memory_buffer out;
|
||||
format_to(out, "For a moment, {} happened.", "nothing");
|
||||
out.data(); // returns a pointer to the formatted data
|
||||
|
||||
The ``fmt::print`` function performs formatting and writes the result to a file:
|
||||
|
||||
@ -54,11 +54,6 @@ The file argument can be omitted in which case the function prints to
|
||||
|
||||
fmt::print("Don't {}\n", "panic");
|
||||
|
||||
If your compiler supports C++11, then the formatting functions are implemented
|
||||
with variadic templates. Otherwise variadic functions are emulated by generating
|
||||
a set of lightweight wrappers. This ensures compatibility with older compilers
|
||||
while providing a natural API.
|
||||
|
||||
The Format API also supports positional arguments useful for localization:
|
||||
|
||||
.. code:: c++
|
||||
@ -106,7 +101,7 @@ the code
|
||||
|
||||
fmt::format("The answer is {:d}", "forty-two");
|
||||
|
||||
throws a ``FormatError`` exception with description
|
||||
throws a ``format_error`` exception with description
|
||||
"unknown format code 'd' for string", because the argument
|
||||
``"forty-two"`` is a string while the format code ``d``
|
||||
only applies to integers.
|
||||
@ -135,6 +130,38 @@ fmt does not attempt to preserve the value of ``errno``, users should not make
|
||||
any assumptions about it and always set it to ``0`` before making any system
|
||||
calls that convey error information via ``errno``.
|
||||
|
||||
Compact binary code
|
||||
-------------------
|
||||
|
||||
Each call to a formatting function results in a compact binary code. For example
|
||||
(`godbolt <https://godbolt.org/g/TZU4KF>`_),
|
||||
|
||||
.. code:: c++
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main() {
|
||||
fmt::print("The answer is {}.", 42);
|
||||
}
|
||||
|
||||
compiles to just
|
||||
|
||||
.. code:: asm
|
||||
|
||||
main: # @main
|
||||
sub rsp, 24
|
||||
mov qword ptr [rsp], 42
|
||||
mov rcx, rsp
|
||||
mov edi, offset .L.str
|
||||
mov esi, 17
|
||||
mov edx, 2
|
||||
call fmt::v5::vprint(fmt::v5::basic_string_view<char>, fmt::v5::format_args)
|
||||
xor eax, eax
|
||||
add rsp, 24
|
||||
ret
|
||||
.L.str:
|
||||
.asciz "The answer is {}."
|
||||
|
||||
.. _portability:
|
||||
|
||||
Portability
|
||||
|
||||
@ -73,7 +73,8 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FMT_HAS_FEATURE(cxx_explicit_conversions)
|
||||
#if FMT_HAS_FEATURE(cxx_explicit_conversions) || \
|
||||
FMT_MSC_VER >= 1800
|
||||
# define FMT_EXPLICIT explicit
|
||||
#else
|
||||
# define FMT_EXPLICIT
|
||||
@ -193,13 +194,11 @@ typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
|
||||
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 a different ``-std`` option than the client code (which is not
|
||||
recommended).
|
||||
\endrst
|
||||
*/
|
||||
template <typename Char>
|
||||
class basic_string_view {
|
||||
@ -238,11 +237,7 @@ class basic_string_view {
|
||||
basic_string_view(const Char *s)
|
||||
: data_(s), size_(std::char_traits<Char>::length(s)) {}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs a string reference from a ``std::basic_string`` object.
|
||||
\endrst
|
||||
*/
|
||||
/** Constructs a string reference from a ``std::basic_string`` object. */
|
||||
template <typename Alloc>
|
||||
FMT_CONSTEXPR basic_string_view(
|
||||
const std::basic_string<Char, Alloc> &s) FMT_NOEXCEPT
|
||||
@ -329,11 +324,7 @@ class basic_buffer {
|
||||
capacity_ = capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Increases the buffer capacity to hold at least *capacity* elements.
|
||||
\endrst
|
||||
*/
|
||||
/** Increases the buffer capacity to hold at least *capacity* elements. */
|
||||
virtual void grow(std::size_t capacity) = 0;
|
||||
|
||||
public:
|
||||
@ -365,11 +356,7 @@ class basic_buffer {
|
||||
size_ = new_size;
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Reserves space to store at least *capacity* elements.
|
||||
\endrst
|
||||
*/
|
||||
/** Reserves space to store at least *capacity* elements. */
|
||||
void reserve(std::size_t capacity) {
|
||||
if (capacity > capacity_)
|
||||
grow(capacity);
|
||||
@ -899,10 +886,8 @@ class basic_format_context :
|
||||
using typename base::iterator;
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs a ``basic_format_context`` object. References to the arguments are
|
||||
stored in the object so make sure they have appropriate lifetimes.
|
||||
\endrst
|
||||
*/
|
||||
basic_format_context(OutputIt out, basic_string_view<char_type> format_str,
|
||||
basic_format_args<basic_format_context> args)
|
||||
@ -986,8 +971,17 @@ class format_arg_store {
|
||||
|
||||
friend class basic_format_args<Context>;
|
||||
|
||||
static FMT_CONSTEXPR uint64_t get_types() {
|
||||
return IS_PACKED ? internal::get_types<Context, Args...>()
|
||||
: -static_cast<int64_t>(NUM_ARGS);
|
||||
}
|
||||
|
||||
public:
|
||||
#if FMT_USE_CONSTEXPR
|
||||
static constexpr uint64_t TYPES = get_types();
|
||||
#else
|
||||
static const uint64_t TYPES;
|
||||
#endif
|
||||
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 405
|
||||
// Workaround an array initialization bug in gcc 4.5 and earlier.
|
||||
@ -1000,10 +994,10 @@ class format_arg_store {
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !FMT_USE_CONSTEXPR
|
||||
template <typename Context, typename ...Args>
|
||||
const uint64_t format_arg_store<Context, Args...>::TYPES = IS_PACKED ?
|
||||
internal::get_types<Context, Args...>() :
|
||||
-static_cast<int64_t>(NUM_ARGS);
|
||||
const uint64_t format_arg_store<Context, Args...>::TYPES = get_types();
|
||||
#endif
|
||||
|
||||
/**
|
||||
\rst
|
||||
|
||||
@ -1381,13 +1381,13 @@ class float_type_checker : private ErrorHandler {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ErrorHandler>
|
||||
template <typename ErrorHandler, typename CharType>
|
||||
class char_specs_checker : public ErrorHandler {
|
||||
private:
|
||||
char type_;
|
||||
CharType type_;
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh)
|
||||
FMT_CONSTEXPR char_specs_checker(CharType type, ErrorHandler eh)
|
||||
: ErrorHandler(eh), type_(type) {}
|
||||
|
||||
FMT_CONSTEXPR void on_int() {
|
||||
@ -3110,8 +3110,10 @@ struct formatter<
|
||||
type_spec, internal::int_type_checker<decltype(eh)>(eh));
|
||||
break;
|
||||
case internal::char_type:
|
||||
handle_char_specs(specs_, internal::char_specs_checker<decltype(eh)>(
|
||||
type_spec, eh));
|
||||
handle_char_specs(
|
||||
specs_,
|
||||
internal::char_specs_checker<decltype(eh), decltype(type_spec)>(
|
||||
type_spec, eh));
|
||||
break;
|
||||
case internal::double_type:
|
||||
case internal::long_double_type:
|
||||
@ -3391,9 +3393,7 @@ std::string to_string(const T &value) {
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Converts *value* to ``std::wstring`` using the default format for type *T*.
|
||||
\endrst
|
||||
*/
|
||||
template <typename T>
|
||||
std::wstring to_wstring(const T &value) {
|
||||
@ -3450,6 +3450,17 @@ inline OutputIt vformat_to(OutputIt out, string_view format_str,
|
||||
return vformat_to<arg_formatter<range>>(range(out), format_str, args);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Formats arguments, writes the result to the output iterator ``out`` and returns
|
||||
the iterator past the end of the output range.
|
||||
|
||||
**Example**::
|
||||
|
||||
std::vector<char> out;
|
||||
fmt::format_to(std::back_inserter(out), "{}", 42);
|
||||
\endrst
|
||||
*/
|
||||
template <typename OutputIt, typename... Args>
|
||||
inline OutputIt format_to(OutputIt out, string_view format_str,
|
||||
const Args & ... args) {
|
||||
@ -3524,7 +3535,10 @@ inline typename std::enable_if<internal::is_format_string<String>::value>::type
|
||||
return vprint(format_str.data(), make_format_args(args...));
|
||||
}
|
||||
|
||||
// Counts the number of characters in the output of format(format_str, args...).
|
||||
/**
|
||||
Returns the number of characters in the output of
|
||||
``format(format_str, args...)``.
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline std::size_t formatted_size(string_view format_str,
|
||||
const Args & ... args) {
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
// output only up to N items from the range.
|
||||
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
|
||||
#define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
|
||||
# define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
@ -72,23 +72,20 @@ void copy(char ch, OutputIterator out) {
|
||||
*out++ = ch;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
namespace internal {
|
||||
|
||||
/// Return true value if T has std::string interface, like std::string_view.
|
||||
template <typename T>
|
||||
class is_like_std_string {
|
||||
template <typename U>
|
||||
static auto check(U *p) -> decltype(p->find('a'), p->length(), p->data(), int());
|
||||
static auto check(U *p) ->
|
||||
decltype(p->find('a'), p->length(), p->data(), int());
|
||||
template <typename>
|
||||
static void check(...);
|
||||
|
||||
public:
|
||||
static FMT_CONSTEXPR_DECL const bool value = !std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
|
||||
template <typename... Ts>
|
||||
struct conditional_helper {};
|
||||
|
||||
@ -104,30 +101,31 @@ struct is_range_<T,typename std::conditional<
|
||||
|
||||
template <typename T>
|
||||
struct is_range {
|
||||
static FMT_CONSTEXPR_DECL const bool value = is_range_<T>::value && !is_like_std_string<T>::value;
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
is_range_<T>::value && !is_like_std_string<T>::value;
|
||||
};
|
||||
|
||||
|
||||
/// tuple_size and tuple_element check.
|
||||
template <typename T>
|
||||
class is_tuple_like_ {
|
||||
template <typename U>
|
||||
static auto check(U *p)
|
||||
-> decltype(std::tuple_size<U>::value,
|
||||
std::declval<typename std::tuple_element<0, U>::type>(), int());
|
||||
static auto check(U *p) ->
|
||||
decltype(std::tuple_size<U>::value,
|
||||
std::declval<typename std::tuple_element<0, U>::type>(), int());
|
||||
template <typename>
|
||||
static void check(...);
|
||||
|
||||
public:
|
||||
static FMT_CONSTEXPR_DECL const bool value = !std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_tuple_like {
|
||||
static FMT_CONSTEXPR_DECL const bool value = is_tuple_like_<T>::value && !is_range_<T>::value;
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
is_tuple_like_<T>::value && !is_range_<T>::value;
|
||||
};
|
||||
|
||||
//=--------------------------------------------------------------------------------------------------------------------
|
||||
template <size_t... Is, class Tuple, class F>
|
||||
void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
|
||||
using std::get;
|
||||
@ -135,21 +133,18 @@ void for_each(std::index_sequence<Is...>, Tuple &&tup, F &&f) noexcept {
|
||||
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
|
||||
(void)_; // blocks warnings
|
||||
}
|
||||
//=--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
template <class T>
|
||||
FMT_CONSTEXPR std::make_index_sequence<std::tuple_size<T>::value>
|
||||
get_indexes(T const &) { return {}; }
|
||||
|
||||
//=--------------------------------------------------------------------------------------------------------------------
|
||||
template <class Tuple, class F>
|
||||
void for_each(Tuple &&tup, F &&f) {
|
||||
const auto indexes = get_indexes(tup);
|
||||
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// =====================================================================================================================
|
||||
template <typename TupleT, typename Char>
|
||||
struct formatter<TupleT, Char,
|
||||
typename std::enable_if<fmt::internal::is_tuple_like<TupleT>::value>::type> {
|
||||
@ -193,7 +188,6 @@ template <typename RangeT, typename Char>
|
||||
struct formatter< RangeT, Char,
|
||||
typename std::enable_if<fmt::internal::is_range<RangeT>::value>::type> {
|
||||
|
||||
|
||||
fmt::formatting_range<Char> formatting;
|
||||
|
||||
template <typename ParseContext>
|
||||
@ -233,4 +227,5 @@ struct formatter< RangeT, Char,
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_RANGES_H_
|
||||
#endif // FMT_RANGES_H_
|
||||
|
||||
|
||||
@ -85,4 +85,4 @@ TEST(RangesTest, FormatStruct) {
|
||||
}
|
||||
|
||||
#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >
|
||||
// 201402L && _MSC_VER >= 1910)
|
||||
// 201402L && _MSC_VER >= 1910)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user