================ @@ -43,80 +55,102 @@ class specific_attr_iterator { mutable Iterator Current; void AdvanceToNext() const { - while (!isa<SpecificAttr>(*Current)) + while (!isa<SpecificAttrs...>(*Current)) ++Current; } void AdvanceToNext(Iterator I) const { - while (Current != I && !isa<SpecificAttr>(*Current)) + while (Current != I && !isa<SpecificAttrs...>(*Current)) ++Current; } public: - using value_type = SpecificAttr *; - using reference = SpecificAttr *; - using pointer = SpecificAttr *; + using value_type = base_type *; + using reference = value_type; + using pointer = value_type; using iterator_category = std::forward_iterator_tag; using difference_type = std::ptrdiff_t; - specific_attr_iterator() = default; - explicit specific_attr_iterator(Iterator i) : Current(i) {} + specific_attr_iterator_impl() = default; + explicit specific_attr_iterator_impl(Iterator i) : Current(i) {} reference operator*() const { AdvanceToNext(); - return cast<SpecificAttr>(*Current); + return cast<base_type>(*Current); } pointer operator->() const { AdvanceToNext(); - return cast<SpecificAttr>(*Current); + return cast<base_type>(*Current); } - specific_attr_iterator& operator++() { + specific_attr_iterator_impl &operator++() { ++Current; return *this; } - specific_attr_iterator operator++(int) { - specific_attr_iterator Tmp(*this); + specific_attr_iterator_impl operator++(int) { + specific_attr_iterator_impl Tmp(*this); ++(*this); return Tmp; } - friend bool operator==(specific_attr_iterator Left, - specific_attr_iterator Right) { + friend bool operator==(specific_attr_iterator_impl Left, + specific_attr_iterator_impl Right) { assert((Left.Current == nullptr) == (Right.Current == nullptr)); if (Left.Current < Right.Current) Left.AdvanceToNext(Right.Current); else Right.AdvanceToNext(Left.Current); return Left.Current == Right.Current; } - friend bool operator!=(specific_attr_iterator Left, - specific_attr_iterator Right) { + friend bool operator!=(specific_attr_iterator_impl Left, + specific_attr_iterator_impl Right) { return !(Left == Right); } }; -template <typename SpecificAttr, typename Container> -inline specific_attr_iterator<SpecificAttr, Container> - specific_attr_begin(const Container& container) { - return specific_attr_iterator<SpecificAttr, Container>(container.begin()); +/// Iterates over a subrange of a collection, only providing attributes that are +/// of a specific type/s. +template <typename Container, typename... SpecificAttrs> +class specific_attr_iterator; + +template <typename SpecificAttr> +class specific_attr_iterator<SpecificAttr> + : public specific_attr_iterator_impl<AttrVec, SpecificAttr> { + using specific_attr_iterator_impl<AttrVec, + SpecificAttr>::specific_attr_iterator_impl; +}; + +template <typename Container, typename... SpecificAttrs> +class specific_attr_iterator ---------------- erichkeane wrote:
I have a version I played with where I put a conversion operator here, so that we can convert to the partial specialization, but it would only be useful in 1 place. The downside we have here is you cannot do: `specific_attr_iterator<MyAttr> Foo = Decl->specific_attr_iterator_begin<MyAttr>()` since the two specializations are 'different' types. I was hoping @ldionne /someone else might have a clever way of combining the uses of these two. https://github.com/llvm/llvm-project/pull/78518 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits