# Conflicts resolved:
#	include/fmt/ranges.h
#	test/ranges-test.cc
This commit is contained in:
Remotion 2018-05-18 23:06:24 +02:00
commit b607de85be
8 changed files with 174 additions and 150 deletions

View File

@ -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)

View File

@ -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
------------------

View File

@ -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&)

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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_

View File

@ -85,4 +85,4 @@ TEST(RangesTest, FormatStruct) {
}
#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >
// 201402L && _MSC_VER >= 1910)
// 201402L && _MSC_VER >= 1910)