This code template <bool IsConst> struct A { void prev() requires BidirectionalIterator<iterator_t<IsConst>>() && BidirectionalIterator<iterator_t<IsConst>>() && BidirectionalIterator<iterator_t<IsConst>>() { --it_; } }; gets formatted into: template <bool IsConst> struct A { void prev() requires BidirectionalIterator<iterator_t<IsConst>>() && BidirectionalIterator<iterator_t<IsConst>>() && BidirectionalIterator<iterator_t<IsConst>>() { --it_; } }; I don't see a reason why the options specified in #32165 shouldn't apply here as well. Also: https://github.com/CaseyCarter/cmcstl2/blob/43b63f6846d80bcd1867f512519bc18841bd961e/include/stl2/detail/iterator/operations.hpp#L25 this code: template <class I> requires Iterator<I>() // Pre: 0 <= n && [i,i+n) constexpr void impl(I& i, difference_type_t<I> n) noexcept(noexcept(++std::declval<I&>())) { STL2_EXPECT(0 <= n); while (n != 0) { --n; ++i; } } gets formatted into template <class I> requires Iterator<I>() // Pre: 0 <= n && [i,i+n) constexpr void impl(I& i, difference_type_t<I> n) noexcept( noexcept(++std::declval<I&>())) { STL2_EXPECT(0 <= n); while (n != 0) { --n; ++i; } } (Note how the constexpr keywords is not aligned with the template keyword).
Ditto Poke, poke. Now that C++20 has been sent out for (what will likely be) its final round of balloting, it would be a good time to work on supporting requires-clauses in clang-format. Think of all the poor, suffering STL maintainers!
I've started to look into the concepts and requires keywords and how clang-format interacts with them (its doesn't really) I'd like @Casey to start with a slightly simpler example (if we could start without the comment that might help) For the following would you expect it to be formatted like this? template <class I, class S> requires Sentinel<S, I>() constexpr void advance(I &i, S bound) noexcept( noexcept(++i != bound)) { while (i != bound) { ++i; } } or something else? I'm trying to look for something of a common starting place between what I see in both https://github.com/CaseyCarter/cmcstl2 and https://github.com/microsoft/STL
(In reply to MyDeveloperDay from comment #2) > I've started to look into the concepts and requires keywords and how > clang-format interacts with them (its doesn't really) > > I'd like @Casey to start with a slightly simpler example (if we could start > without the comment that might help) > > For the following would you expect it to be formatted like this? > > template <class I, class S> > requires Sentinel<S, I>() > constexpr void advance(I &i, S bound) noexcept( noexcept(++i != bound)) { > while (i != bound) { > ++i; > } > } Today, I'd format this as: template <class I, class S> requires Sentinel<S, I>() constexpr void advance(I& i, S bound) noexcept(noexcept(++i != bound)) { while (i != bound) { ++i; } } with the requires-clause indented once relative to the template declaration, and continuation lines one indent deeper: template <class I, class S> requires Sentinel<S, I>() && // ... && OtherConcept1<I> && // ... && OtherConcept2<I> && // ... && OtherConcept3<I> && // ... constexpr void advance(I& i, S bound) noexcept(noexcept(++i != bound)) { while (i != bound) { ++i; } } which probably follows from how clang normally wraps expressions across lines. I try to format trailing requires-clauses exactly as you've put the noexcept-specifier in the example, but wrapping the whole thing onto the next line if it won't fit on the primary declaration line and only splitting if the requires-clause itself is longer than one line: template <class I> void f(I i) requires Concept1<I> && Concept2<i> { // ... } template <class I> long_return_type g(I i) requires Concept1<I> && Concept2<i> && VeryVeryVeryVeryLongConcept<I> { // ... } template <class I> long_return_type h(I i) requires Concept1<I> && Concept2<i> && VeryVeryVeryVeryLongConcept<I> && OtherLongConcept<I> { // ... } > or something else? I'm trying to look for something of a common starting > place between what I see in both > > https://github.com/CaseyCarter/cmcstl2 > and > https://github.com/microsoft/STL Please ignore cmcstl2: there a few different styles there that we experimented with over the years, and it was never really made consistent. range-v3 is even worse: its style represents a set of compromises to get the least offensive output from clang-format. I have no idea how libstdc++ is formatting their concepts usage, but they have C++20 Ranges implemented so they may have an interesting counterpoint to my style.
I'm working on it.