-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exclude recursive ranges from the formatter specialization for ranges #2974
Changes from 8 commits
d511485
6d14574
26a2844
c6f372b
a1ec9fc
e4c2e72
7b05da7
bfff7ed
c03288b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -390,22 +390,36 @@ using range_formatter_type = conditional_t< | |
template <typename R> | ||
using maybe_const_range = | ||
conditional_t<has_const_begin_end<R>::value, const R, R>; | ||
|
||
template <typename R> | ||
struct is_not_recursive_range : bool_constant< | ||
!std::is_same<detail::uncvref_type<R>, R>::value> {}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Contrary to the name of this trait it only checks recursiveness but not whether R is a range. I suggest adding is_range check here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, we want to prevent instantiation if the is_recursive predicate unless the is_range predicate has evaluated to true. See above. We could rename it to something different, such as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, please add a comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment added, also relating to P2286. |
||
|
||
template <typename R, typename Char> | ||
struct is_formattable_delayed : is_formattable< | ||
detail::uncvref_type<detail::maybe_const_range<R>>, Char> { | ||
}; | ||
|
||
template <typename R, typename Char> | ||
struct has_fallback_formatter_delayed : detail::has_fallback_formatter< | ||
detail::uncvref_type<detail::maybe_const_range<R>>, Char> { | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are these for? I'd suggest keeping them inlined as before. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The whole point of this P/R is to ensure that the individual parts of the condition are evaluated in short-circuit manner. In C++ without language concepts this is only possible by defining type predicates that get only evaluated if the corresponding predicate template class definition becomes instantiated. Due to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you clarify this in a comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd suggest either adding a generic thing to delay instantiation, like so: template <template <class...> class F, typename... Args> struct delayed : F<Args...> { }; to be used as: disjunction<
delayed<is_formattable, detail::uncvref_type<detail::maybe_const_range<R>>, Char>,
delayed<detail::has_fallback_formatter, detail::uncvref_type<detail::maybe_const_range<R>>, Char>
> or, if we're going to manually do our own thing, do all of it together: template <class T, class Char>
struct delayed_fallback_formattable
: disjunction<
is_formattable<T, Char>,
detail::has_fallback_formatter<T, Char>>
{ }; to be used as: conjunction<
A,
B,
delayed_fallback_formattable<detail::uncvref_type<detail::maybe_const_range<R>>, Char>
> Put differently - instead of writing two bespoke delayed traits, write either one generic delayer or one bespoke delayed trait. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a good suggestion but note that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh. Ok that makes sense then. When you say soon, how soon? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I merged now has_fallback_formatter_delayed into is_formattable_delayed and got rid of the former. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In the next major release about a year from now. |
||
|
||
} // namespace detail | ||
|
||
template <typename R, typename Char> | ||
struct formatter< | ||
R, Char, | ||
enable_if_t< | ||
conjunction<fmt::is_range<R, Char> | ||
// Workaround a bug in MSVC 2017 and earlier. | ||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1920 | ||
, | ||
disjunction< | ||
is_formattable<detail::uncvref_type<detail::maybe_const_range<R>>, | ||
Char>, | ||
detail::has_fallback_formatter< | ||
detail::uncvref_type<detail::maybe_const_range<R>>, Char> | ||
> | ||
conjunction<fmt::is_range<R, Char>, | ||
detail::is_not_recursive_range<R> | ||
// Workaround a bug in MSVC 2015 and earlier. | ||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1900 | ||
, | ||
disjunction< | ||
detail::is_formattable_delayed<R, Char>, | ||
detail::has_fallback_formatter_delayed<R, Char> | ||
> | ||
#endif | ||
>::value | ||
>> { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_not_recursive_range -> is_nonrecursive_range
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed as suggested.