Commit a6ad29aa authored by Victor Zverovich's avatar Victor Zverovich

Update <format>

parent 52eb3fe2
...@@ -132,15 +132,17 @@ namespace std { ...@@ -132,15 +132,17 @@ namespace std {
enum indexing { unknown, manual, automatic }; // exposition only enum indexing { unknown, manual, automatic }; // exposition only
indexing indexing_; // exposition only indexing indexing_; // exposition only
size_t next_arg_id_; // exposition only size_t next_arg_id_; // exposition only
size_t num_args_; // exposition only
public: public:
explicit constexpr basic_format_parse_context(basic_string_view<charT> fmt) noexcept; explicit constexpr basic_format_parse_context(basic_string_view<charT> fmt,
size_t num_args = 0) noexcept;
basic_format_parse_context(const basic_format_parse_context&) = delete; basic_format_parse_context(const basic_format_parse_context&) = delete;
basic_format_parse_context& operator=(const basic_format_parse_context&) = delete; basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
constexpr const_iterator begin() const noexcept; constexpr const_iterator begin() const noexcept;
constexpr const_iterator end() const noexcept; constexpr const_iterator end() const noexcept;
constexpr void advance_to(iterator it); constexpr void advance_to(const_iterator it);
constexpr size_t next_arg_id(); constexpr size_t next_arg_id();
constexpr void check_arg_id(size_t id); constexpr void check_arg_id(size_t id);
...@@ -154,8 +156,10 @@ namespace std { ...@@ -154,8 +156,10 @@ namespace std {
namespace std { namespace std {
template<class charT> template<class charT>
/* explicit */ constexpr basic_format_parse_context<charT>::basic_format_parse_context(basic_string_view<charT> fmt) noexcept /* explicit */ constexpr basic_format_parse_context<charT>::
: begin_(fmt.begin()), end_(fmt.end()), indexing_(unknown), next_arg_id_(0) {} basic_format_parse_context(basic_string_view<charT> fmt,
size_t num_args) noexcept
: begin_(fmt.begin()), end_(fmt.end()), indexing_(unknown), next_arg_id_(0), num_args_(num_args) {}
template<class charT> template<class charT>
constexpr typename basic_format_parse_context<charT>::const_iterator basic_format_parse_context<charT>::begin() const noexcept { return begin_; } constexpr typename basic_format_parse_context<charT>::const_iterator basic_format_parse_context<charT>::begin() const noexcept { return begin_; }
...@@ -176,7 +180,10 @@ constexpr size_t basic_format_parse_context<charT>::next_arg_id() { ...@@ -176,7 +180,10 @@ constexpr size_t basic_format_parse_context<charT>::next_arg_id() {
} }
template<class charT> template<class charT>
constexpr void basic_format_parse_context<charT>::check_arg_id(size_t) { constexpr void basic_format_parse_context<charT>::check_arg_id(size_t id) {
// clang doesn't support __builtin_is_constant_evaluated yet
//if (!(!__builtin_is_constant_evaluated() || id < num_args_))
// throw format_error(invalid index is out of range");
if (indexing_ == automatic) if (indexing_ == automatic)
throw format_error("automatic to manual indexing"); throw format_error("automatic to manual indexing");
if (indexing_ == unknown) if (indexing_ == unknown)
...@@ -186,17 +193,15 @@ constexpr void basic_format_parse_context<charT>::check_arg_id(size_t) { ...@@ -186,17 +193,15 @@ constexpr void basic_format_parse_context<charT>::check_arg_id(size_t) {
// http://fmtlib.net/Text%20Formatting.html#format.context // http://fmtlib.net/Text%20Formatting.html#format.context
namespace std { namespace std {
template<class O, class charT> FMT_REQUIRES(OutputIterator<O, const charT&>) template<class Out, class charT>
class basic_format_context { class basic_format_context {
basic_format_args<basic_format_context> args_; // exposition only basic_format_args<basic_format_context> args_; // exposition only
O out_; // exposition only Out out_; // exposition only
public: public:
using iterator = O; using iterator = Out;
using char_type = charT; using char_type = charT;
template<class T> using formatter_type = formatter<T, charT>;
template<class T>
using formatter_type = formatter<T>;
basic_format_arg<basic_format_context> arg(size_t id) const; basic_format_arg<basic_format_context> arg(size_t id) const;
...@@ -205,7 +210,7 @@ namespace std { ...@@ -205,7 +210,7 @@ namespace std {
// Implementation details: // Implementation details:
using format_arg = basic_format_arg<basic_format_context>; using format_arg = basic_format_arg<basic_format_context>;
basic_format_context(O out, basic_format_args<basic_format_context> args, fmt::internal::locale_ref) basic_format_context(Out out, basic_format_args<basic_format_context> args, fmt::internal::locale_ref)
: args_(args), out_(out) {} : args_(args), out_(out) {}
fmt::internal::error_handler error_handler() const { return {}; } fmt::internal::error_handler error_handler() const { return {}; }
basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const { basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const {
...@@ -256,53 +261,56 @@ namespace std { ...@@ -256,53 +261,56 @@ namespace std {
class handle; class handle;
private: private:
using char_type = typename Context::char_type; // exposition only using char_type = typename Context::char_type; // exposition only
public: // public to workaround a bug in clang
variant<monostate, bool, char_type, variant<monostate, bool, char_type,
int, unsigned int, long long int, unsigned long long int, int, unsigned int, long long int, unsigned long long int,
double, long double, double, long double,
const char_type*, basic_string_view<char_type>, const char_type*, basic_string_view<char_type>,
const void*, handle> value; // exposition only const void*, handle> value; // exposition only
private: template<typename T,
template<
FMT_CONCEPT(Integral) I,
typename = enable_if_t< typename = enable_if_t<
std::is_same_v<I, bool> || std::is_same_v<T, bool> ||
std::is_same_v<I, char_type> || std::is_same_v<T, char_type> ||
(std::is_same_v<I, char> && std::is_same_v<char_type, wchar_t>) || (std::is_same_v<T, char> && std::is_same_v<char_type, wchar_t>) ||
detail::is_standard_integer_v<I> || detail::is_standard_integer_v<T> ||
detail::is_standard_unsigned_integer_v<I> || detail::is_standard_unsigned_integer_v<T> ||
is_default_constructible_v<typename Context::template formatter_type<I>> is_default_constructible_v<typename Context::template formatter_type<T>>
>> >> explicit basic_format_arg(const T& v) noexcept; // exposition only
explicit basic_format_arg(const I& n) noexcept; // exposition only explicit basic_format_arg(float n) noexcept; // exposition only
explicit basic_format_arg(float n) noexcept; // exposition only explicit basic_format_arg(double n) noexcept; // exposition only
explicit basic_format_arg(double n) noexcept; // exposition only explicit basic_format_arg(long double n) noexcept; // exposition only
explicit basic_format_arg(long double n) noexcept; // exposition only explicit basic_format_arg(const char_type* s); // exposition only
explicit basic_format_arg(const char_type* s) noexcept; // exposition only
explicit basic_format_arg(nullptr_t) noexcept; // exposition only
template<class traits> template<class traits>
explicit basic_format_arg( explicit basic_format_arg(
basic_string_view<char_type, traits> s) noexcept; // exposition only basic_string_view<char_type, traits> s) noexcept; // exposition only
template<class traits, class Allocator> template<class traits, class Allocator>
explicit basic_format_arg( explicit basic_format_arg(
const basic_string<char_type, traits, Allocator>& s) noexcept; // exposition only const basic_string<char_type, traits, Allocator>& s) noexcept; // exposition only
template<class T, typename = std::enable_if_t<std::is_same_v<T, void>>> explicit basic_format_arg(nullptr_t) noexcept; // exposition only
explicit basic_format_arg(const T* p) noexcept; // exposition only
//template<class Visitor> template<class T, typename = enable_if_t<is_void_v<T>>>
// friend auto std::visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); explicit basic_format_arg(const T* p) noexcept; // exposition only
template<class Ctx, class... Args> // Fails due to a bug in clang
friend format_arg_store<Ctx, Args...> //template<class Visitor, class Ctx>
make_format_args(const Args&... args); // exposition only // friend auto visit_format_arg(Visitor&& vis,
// basic_format_arg<Ctx> arg); // exposition only
friend auto get_value(basic_format_arg arg) {
return arg.value;
}
template <typename T, typename Char> friend struct detail::formatter; template <typename T, typename Char> friend struct detail::formatter;
template<class Ctx, class... Args>
friend format_arg_store<Ctx, Args...>
make_format_args(const Args&... args); // exposition only
public: public:
basic_format_arg() noexcept; basic_format_arg() noexcept;
...@@ -315,22 +323,21 @@ template<class Context> ...@@ -315,22 +323,21 @@ template<class Context>
basic_format_arg<Context>::basic_format_arg() noexcept {} basic_format_arg<Context>::basic_format_arg() noexcept {}
template<class Context> template<class Context>
template<FMT_CONCEPT(Integral) I, typename> template<class T, typename> /* explicit */ basic_format_arg<Context>::basic_format_arg(const T& v) noexcept {
/* explicit */ basic_format_arg<Context>::basic_format_arg(const I& n) noexcept { if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, char_type>)
if constexpr (std::is_same_v<I, bool> || std::is_same_v<I, char_type>) value = v;
value = n; else if constexpr (std::is_same_v<T, char> && std::is_same_v<char_type, wchar_t>)
else if constexpr (std::is_same_v<I, char> && std::is_same_v<char_type, wchar_t>) value = static_cast<wchar_t>(v);
value = static_cast<wchar_t>(n); else if constexpr (detail::is_standard_integer_v<T> && sizeof(T) <= sizeof(int))
else if constexpr (detail::is_standard_integer_v<I> && sizeof(I) <= sizeof(int)) value = static_cast<int>(v);
value = static_cast<int>(n); else if constexpr (detail::is_standard_unsigned_integer_v<T> && sizeof(T) <= sizeof(unsigned))
else if constexpr (detail::is_standard_unsigned_integer_v<I> && sizeof(I) <= sizeof(unsigned)) value = static_cast<unsigned>(v);
value = static_cast<unsigned>(n); else if constexpr (detail::is_standard_integer_v<T>)
else if constexpr (detail::is_standard_integer_v<I>) value = static_cast<long long int>(v);
value = static_cast<long long int>(n); else if constexpr (detail::is_standard_unsigned_integer_v<T>)
else if constexpr (detail::is_standard_unsigned_integer_v<I>) value = static_cast<unsigned long long int>(v);
value = static_cast<unsigned long long int>(n); else if constexpr (is_default_constructible_v<typename Context::template formatter_type<T>>)
else if constexpr (is_default_constructible_v<typename Context::template formatter_type<I>>) value = handle(v);
value = handle(n);
} }
template<class Context> template<class Context>
...@@ -346,7 +353,7 @@ template<class Context> ...@@ -346,7 +353,7 @@ template<class Context>
: value(n) {} : value(n) {}
template<class Context> template<class Context>
/* explicit */ basic_format_arg<Context>::basic_format_arg(const typename basic_format_arg<Context>::char_type* s) noexcept /* explicit */ basic_format_arg<Context>::basic_format_arg(const typename basic_format_arg<Context>::char_type* s)
: value(s) { : value(s) {
assert(s != nullptr); assert(s != nullptr);
} }
...@@ -386,7 +393,7 @@ namespace std { ...@@ -386,7 +393,7 @@ namespace std {
template<class T> explicit handle(const T& val) noexcept; // exposition only template<class T> explicit handle(const T& val) noexcept; // exposition only
friend class basic_format_arg<Context>; friend class basic_format_arg<Context>; // exposition only
public: public:
void format(basic_format_parse_context<char_type>&, Context& ctx) const; void format(basic_format_parse_context<char_type>&, Context& ctx) const;
...@@ -397,10 +404,10 @@ namespace std { ...@@ -397,10 +404,10 @@ namespace std {
template<class Context> template<class Context>
template<class T> /* explicit */ basic_format_arg<Context>::handle::handle(const T& val) noexcept template<class T> /* explicit */ basic_format_arg<Context>::handle::handle(const T& val) noexcept
: ptr_(&val), format_([](basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx, const void* ptr) { : ptr_(&val), format_([](basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx, const void* ptr) {
typename Context::template formatter_type<T> f; typename Context::template formatter_type<T> f;
parse_ctx.advance_to(f.parse(parse_ctx)); parse_ctx.advance_to(f.parse(parse_ctx));
format_ctx.advance_to(f.format(*static_cast<const T*>(ptr), format_ctx)); format_ctx.advance_to(f.format(*static_cast<const T*>(ptr), format_ctx));
}) {} }) {}
template<class Context> template<class Context>
void basic_format_arg<Context>::handle::format(basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx) const { void basic_format_arg<Context>::handle::format(basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx) const {
...@@ -410,7 +417,7 @@ void basic_format_arg<Context>::handle::format(basic_format_parse_context<char_t ...@@ -410,7 +417,7 @@ void basic_format_arg<Context>::handle::format(basic_format_parse_context<char_t
// http://fmtlib.net/Text%20Formatting.html#format.visit // http://fmtlib.net/Text%20Formatting.html#format.visit
template<class Visitor, class Context> template<class Visitor, class Context>
auto visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg) { auto visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg) {
return visit(vis, arg.value); return visit(vis, get_value(arg));
} }
} }
...@@ -465,7 +472,7 @@ template<class Context /*= format_context*/, class... Args> ...@@ -465,7 +472,7 @@ template<class Context /*= format_context*/, class... Args>
// http://fmtlib.net/Text%20Formatting.html#format.make_wargs // http://fmtlib.net/Text%20Formatting.html#format.make_wargs
template<class... Args> template<class... Args>
format_arg_store<wformat_context, Args...> make_wformat_args(const Args&... args) { format_arg_store<wformat_context, Args...> make_wformat_args(const Args&... args) {
return {basic_format_arg<wformat_context>(args)...}; return make_format_args<wformat_context>(args...);
} }
} }
...@@ -543,7 +550,7 @@ inline fmt::internal::type get_type(basic_format_arg<Context> arg) { ...@@ -543,7 +550,7 @@ inline fmt::internal::type get_type(basic_format_arg<Context> arg) {
return fmt::internal::string_type; return fmt::internal::string_type;
if (std::is_same_v<T, const void*>) if (std::is_same_v<T, const void*>)
return fmt::internal::pointer_type; return fmt::internal::pointer_type;
assert(arg.value.index() == 12); assert(get_value(arg).index() == 12);
return fmt::internal::custom_type; return fmt::internal::custom_type;
}, arg); }, arg);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment