@@ -658,6 +658,14 @@ concept _Formattable_with = semiregular<_Formatter>
658
658
{ __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>;
659
659
};
660
660
661
+ template <class _Ty, class _Context, class _Formatter = _Context::template formatter_type<remove_const_t<_Ty>>>
662
+ concept _Formattable_with_non_const = semiregular<_Formatter>
663
+ && requires(_Formatter& __f, _Ty&& __t, _Context __fc,
664
+ basic_format_parse_context<typename _Context::char_type> __pc) {
665
+ { __f.parse(__pc) } -> same_as<typename decltype(__pc)::iterator>;
666
+ { __f.format(__t, __fc) } -> same_as<typename _Context::iterator>;
667
+ };
668
+
661
669
template <class _Ty, class _CharT>
662
670
inline constexpr bool _Is_basic_string_like_for = false;
663
671
@@ -711,15 +719,23 @@ public:
711
719
using _Td = remove_const_t<_Ty>;
712
720
// doesn't drop const-qualifier per an unnumbered LWG issue
713
721
using _Tq = conditional_t<_Formattable_with<const _Ty, _Context>, const _Ty, _Ty>;
722
+ if constexpr (_Formattable_with_non_const<_Tq, _Context>) {
723
+ static_assert(_Formattable_with<_Tq, _Context>,
724
+ "The format() member function can't be called on const formatter<T>. "
725
+ "To make the formatter usable, add const to format(). "
726
+ "See N4971 [format.arg]/12, [format.formattable], and [formatter.requirements].");
727
+ } else {
728
+ static_assert(_Formattable_with<_Tq, _Context>,
729
+ "Cannot format an argument. "
730
+ "To make this type formattable, provide a formatter<T> specialization. "
731
+ "See N4971 [format.arg]/12, [format.formattable], and [formatter.requirements].");
732
+ }
733
+
714
734
typename _Context::template formatter_type<_Td> _Formatter;
715
735
_Parse_ctx.advance_to(_Formatter.parse(_Parse_ctx));
716
736
_Format_ctx.advance_to(
717
737
_Formatter.format(*const_cast<_Tq*>(static_cast<const _Td*>(_Ptr)), _Format_ctx));
718
- }) {
719
- // ditto doesn't drop const-qualifier
720
- using _Tq = conditional_t<_Formattable_with<const _Ty, _Context>, const _Ty, _Ty>;
721
- static_assert(_Formattable_with<_Tq, _Context>);
722
- }
738
+ }) {}
723
739
724
740
void format(basic_format_parse_context<_CharType>& _Parse_ctx, _Context& _Format_ctx) const {
725
741
_Format(_Parse_ctx, _Format_ctx, _Ptr);
@@ -3715,20 +3731,22 @@ _EXPORT_STD using wformat_args = basic_format_args<wformat_context>;
3715
3731
3716
3732
_EXPORT_STD template <class _Context = format_context, class... _Args>
3717
3733
_NODISCARD auto make_format_args(_Args&... _Vals) {
3718
- // TRANSITION, should cite the new working draft
3719
- static_assert((_Formattable_with<remove_const_t<_Args>, _Context> && ...),
3720
- "Cannot format an argument. To make type T formattable, provide a formatter<T> specialization. "
3721
- "See N4964 [format.arg.store]/2 (along with modification in P2905R2) and [formatter.requirements].");
3734
+ if constexpr ((_Formattable_with_non_const<remove_const_t<_Args>, _Context> && ...)) {
3735
+ static_assert((_Formattable_with<remove_const_t<_Args>, _Context> && ...),
3736
+ "The format() member function can't be called on const formatter<T>. "
3737
+ "To make the formatter usable, add const to format(). "
3738
+ "See N4971 [format.arg.store]/2 and [formatter.requirements].");
3739
+ } else {
3740
+ static_assert((_Formattable_with<remove_const_t<_Args>, _Context> && ...),
3741
+ "Cannot format an argument. To make T formattable, provide a formatter<T> specialization. "
3742
+ "See N4971 [format.arg.store]/2 and [formatter.requirements].");
3743
+ }
3722
3744
return _Format_arg_store<_Context, _Args...>{_Vals...};
3723
3745
}
3724
3746
3725
3747
_EXPORT_STD template <class... _Args>
3726
3748
_NODISCARD auto make_wformat_args(_Args&... _Vals) {
3727
- // TRANSITION, should cite the new working draft
3728
- static_assert((_Formattable_with<remove_const_t<_Args>, wformat_context> && ...),
3729
- "Cannot format an argument. To make type T formattable, provide a formatter<T> specialization. "
3730
- "See N4964 [format.arg.store]/2 (along with modification in P2905R2) and [formatter.requirements].");
3731
- return _Format_arg_store<wformat_context, _Args...>{_Vals...};
3749
+ return _STD make_format_args<wformat_context>(_Vals...);
3732
3750
}
3733
3751
3734
3752
_FMT_P2286_BEGIN
0 commit comments