diff --git a/include/format b/include/format index 633a731c..2427e79d 100644 --- a/include/format +++ b/include/format @@ -132,15 +132,17 @@ namespace std { enum indexing { unknown, manual, automatic }; // exposition only indexing indexing_; // exposition only size_t next_arg_id_; // exposition only + size_t num_args_; // exposition only public: - explicit constexpr basic_format_parse_context(basic_string_view fmt) noexcept; + explicit constexpr basic_format_parse_context(basic_string_view fmt, + size_t num_args = 0) noexcept; basic_format_parse_context(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 end() const noexcept; - constexpr void advance_to(iterator it); + constexpr void advance_to(const_iterator it); constexpr size_t next_arg_id(); constexpr void check_arg_id(size_t id); @@ -154,8 +156,10 @@ namespace std { namespace std { template -/* explicit */ constexpr basic_format_parse_context::basic_format_parse_context(basic_string_view fmt) noexcept -: begin_(fmt.begin()), end_(fmt.end()), indexing_(unknown), next_arg_id_(0) {} +/* explicit */ constexpr basic_format_parse_context:: + basic_format_parse_context(basic_string_view fmt, + size_t num_args) noexcept +: begin_(fmt.begin()), end_(fmt.end()), indexing_(unknown), next_arg_id_(0), num_args_(num_args) {} template constexpr typename basic_format_parse_context::const_iterator basic_format_parse_context::begin() const noexcept { return begin_; } @@ -176,7 +180,10 @@ constexpr size_t basic_format_parse_context::next_arg_id() { } template -constexpr void basic_format_parse_context::check_arg_id(size_t) { +constexpr void basic_format_parse_context::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) throw format_error("automatic to manual indexing"); if (indexing_ == unknown) @@ -186,17 +193,15 @@ constexpr void basic_format_parse_context::check_arg_id(size_t) { // http://fmtlib.net/Text%20Formatting.html#format.context namespace std { - template FMT_REQUIRES(OutputIterator) + template class basic_format_context { basic_format_args args_; // exposition only - O out_; // exposition only + Out out_; // exposition only public: - using iterator = O; + using iterator = Out; using char_type = charT; - - template - using formatter_type = formatter; + template using formatter_type = formatter; basic_format_arg arg(size_t id) const; @@ -205,7 +210,7 @@ namespace std { // Implementation details: using format_arg = basic_format_arg; - basic_format_context(O out, basic_format_args args, fmt::internal::locale_ref) + basic_format_context(Out out, basic_format_args args, fmt::internal::locale_ref) : args_(args), out_(out) {} fmt::internal::error_handler error_handler() const { return {}; } basic_format_arg arg(fmt::basic_string_view) const { @@ -256,52 +261,55 @@ namespace std { class handle; 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, - const void*, handle> value; // exposition only + const void*, handle> value; // exposition only - private: - template< - FMT_CONCEPT(Integral) I, + template || - std::is_same_v || - (std::is_same_v && std::is_same_v) || - detail::is_standard_integer_v || - detail::is_standard_unsigned_integer_v || - is_default_constructible_v> - >> - explicit basic_format_arg(const I& 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(long double n) noexcept; // exposition only - explicit basic_format_arg(const char_type* s) noexcept; // exposition only - explicit basic_format_arg(nullptr_t) noexcept; // exposition only + std::is_same_v || + std::is_same_v || + (std::is_same_v && std::is_same_v) || + detail::is_standard_integer_v || + detail::is_standard_unsigned_integer_v || + is_default_constructible_v> + >> explicit basic_format_arg(const T& v) 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(long double n) noexcept; // exposition only + explicit basic_format_arg(const char_type* s); // exposition only template explicit basic_format_arg( - basic_string_view s) noexcept; // exposition only + basic_string_view s) noexcept; // exposition only template explicit basic_format_arg( - const basic_string& s) noexcept; // exposition only + const basic_string& s) noexcept; // exposition only - template>> - explicit basic_format_arg(const T* p) noexcept; // exposition only + explicit basic_format_arg(nullptr_t) noexcept; // exposition only - //template - // friend auto std::visit_format_arg(Visitor&& vis, basic_format_arg arg); + template>> + explicit basic_format_arg(const T* p) noexcept; // exposition only + + // Fails due to a bug in clang + //template + // friend auto visit_format_arg(Visitor&& vis, + // basic_format_arg arg); // exposition only + + friend auto get_value(basic_format_arg arg) { + return arg.value; + } + + template friend struct detail::formatter; template friend format_arg_store - make_format_args(const Args&... args); // exposition only - - template friend struct detail::formatter; + make_format_args(const Args&... args); // exposition only public: basic_format_arg() noexcept; @@ -315,22 +323,21 @@ template basic_format_arg::basic_format_arg() noexcept {} template -template -/* explicit */ basic_format_arg::basic_format_arg(const I& n) noexcept { - if constexpr (std::is_same_v || std::is_same_v) - value = n; - else if constexpr (std::is_same_v && std::is_same_v) - value = static_cast(n); - else if constexpr (detail::is_standard_integer_v && sizeof(I) <= sizeof(int)) - value = static_cast(n); - else if constexpr (detail::is_standard_unsigned_integer_v && sizeof(I) <= sizeof(unsigned)) - value = static_cast(n); - else if constexpr (detail::is_standard_integer_v) - value = static_cast(n); - else if constexpr (detail::is_standard_unsigned_integer_v) - value = static_cast(n); - else if constexpr (is_default_constructible_v>) - value = handle(n); +template /* explicit */ basic_format_arg::basic_format_arg(const T& v) noexcept { + if constexpr (std::is_same_v || std::is_same_v) + value = v; + else if constexpr (std::is_same_v && std::is_same_v) + value = static_cast(v); + else if constexpr (detail::is_standard_integer_v && sizeof(T) <= sizeof(int)) + value = static_cast(v); + else if constexpr (detail::is_standard_unsigned_integer_v && sizeof(T) <= sizeof(unsigned)) + value = static_cast(v); + else if constexpr (detail::is_standard_integer_v) + value = static_cast(v); + else if constexpr (detail::is_standard_unsigned_integer_v) + value = static_cast(v); + else if constexpr (is_default_constructible_v>) + value = handle(v); } template @@ -346,7 +353,7 @@ template : value(n) {} template -/* explicit */ basic_format_arg::basic_format_arg(const typename basic_format_arg::char_type* s) noexcept +/* explicit */ basic_format_arg::basic_format_arg(const typename basic_format_arg::char_type* s) : value(s) { assert(s != nullptr); } @@ -386,7 +393,7 @@ namespace std { template explicit handle(const T& val) noexcept; // exposition only - friend class basic_format_arg; + friend class basic_format_arg; // exposition only public: void format(basic_format_parse_context&, Context& ctx) const; @@ -397,10 +404,10 @@ namespace std { template template /* explicit */ basic_format_arg::handle::handle(const T& val) noexcept : ptr_(&val), format_([](basic_format_parse_context& parse_ctx, Context& format_ctx, const void* ptr) { - typename Context::template formatter_type f; - parse_ctx.advance_to(f.parse(parse_ctx)); - format_ctx.advance_to(f.format(*static_cast(ptr), format_ctx)); -}) {} + typename Context::template formatter_type f; + parse_ctx.advance_to(f.parse(parse_ctx)); + format_ctx.advance_to(f.format(*static_cast(ptr), format_ctx)); + }) {} template void basic_format_arg::handle::format(basic_format_parse_context& parse_ctx, Context& format_ctx) const { @@ -410,7 +417,7 @@ void basic_format_arg::handle::format(basic_format_parse_context auto visit_format_arg(Visitor&& vis, basic_format_arg arg) { - return visit(vis, arg.value); + return visit(vis, get_value(arg)); } } @@ -465,7 +472,7 @@ template // http://fmtlib.net/Text%20Formatting.html#format.make_wargs template format_arg_store make_wformat_args(const Args&... args) { - return {basic_format_arg(args)...}; + return make_format_args(args...); } } @@ -543,7 +550,7 @@ inline fmt::internal::type get_type(basic_format_arg arg) { return fmt::internal::string_type; if (std::is_same_v) return fmt::internal::pointer_type; - assert(arg.value.index() == 12); + assert(get_value(arg).index() == 12); return fmt::internal::custom_type; }, arg); }