SoFunction
Updated on 2025-04-14

Summary of how to use C++ transformation iterator

1. Source code

template<class _UnaryFuncT, class _SourceIteratorT, class _SourceValueT, class _ValueT>
        class transform_iterator :
            public __composition_iterator<transform_iterator<_UnaryFuncT, _SourceIteratorT, _SourceValueT, _ValueT>,
            _SourceIteratorT, _SourceValueT> {
        public:
            using __parent_t = __composition_iterator<transform_iterator<_UnaryFuncT, _SourceIteratorT, _SourceValueT, _ValueT>,
                _SourceIteratorT, _SourceValueT>;
            typedef convert_pointer_t<_SourceIteratorT, _ValueT> __pointer_t;
            typedef std::iterator_traits<__pointer_t> __std_iterator_traits;
            _UnaryFuncT func;
            typedef typename _SourceIteratorT::iterator_category iterator_category;
            typedef typename _SourceIteratorT::difference_type difference_type;
            typedef typename __std_iterator_traits::value_type value_type;
            typedef typename __std_iterator_traits::pointer pointer;
            typedef typename __std_iterator_traits::reference reference;

            transform_iterator() : __parent_t() {};

            transform_iterator(_SourceIteratorT const& it, _UnaryFuncT f) : func(f), __parent_t(it) {}

            explicit transform_iterator(_SourceIteratorT const& it) : __parent_t(it) {};

            transform_iterator(const transform_iterator& other) : __parent_t(other.source_it), func() {}

            transform_iterator& operator=(const transform_iterator& other) {
                this->source_it = other.source_it;
                this->func = ;
                return *this;
            }

            transform_iterator(transform_iterator&& other) : __parent_t(other.source_it), func() {
                this->source_it = other.source_it;
            }

            transform_iterator& operator=(transform_iterator&& other) {
                this->source_it = other.source_it;
                this->func = ;
                return *this;
            }

            inline reference operator*() const { return func(*this->source_it); }

            inline pointer operator->() const { return &func(*this->source_it); }

            template<typename ReferenceT = reference>
            inline std::enable_if_t<std::is_same_v<ReferenceT, reference>&&
                std::is_same_v<iterator_category, std::random_access_iterator_tag>, ReferenceT>
                operator[](difference_type __n) const {
                static_assert(std::is_same_v<iterator_category, std::random_access_iterator_tag>);
                return func(this->source_it[__n]);
            }

            inline const pointer base() const { return &func(*(this->source_it)); }

        };


        /*!
         * @brief   Convenient method to make a transform_iterator with template deduction, for a given Conversion
         */
        template<typename _ConversionT, typename _SourceIteratorT>
        slam::transform_iterator<_ConversionT,
            _SourceIteratorT,
            typename _SourceIteratorT::value_type,
            typename _ConversionT::value_type> make_transform(_SourceIteratorT it,
                _ConversionT) {
            static_assert(std::is_same_v<typename _ConversionT::conversion_category, reference_conversion_tag>,
                "A transform iterator can only be applied with a conversion mapping two references");
            return slam::transform_iterator<_ConversionT, _SourceIteratorT,
                typename _SourceIteratorT::value_type, typename _ConversionT::value_type>(it);
        };

        /**
         * @brief Returns the pair <begin, end> transform iterators of a collection, for a given Conversion
         */
        template<typename _ConversionT, typename _SourceCollection>
        std::pair<slam::transform_iterator<_ConversionT,
            typename _SourceCollection::iterator,
            typename _SourceCollection::iterator::value_type,
            typename _ConversionT::value_type>,
            slam::transform_iterator<_ConversionT,
            typename _SourceCollection::iterator,
            typename _SourceCollection::iterator::value_type,
            typename _ConversionT::value_type>> make_transform_collection(_SourceCollection& collection,
                _ConversionT) {
            static_assert(std::is_same_v<typename _ConversionT::conversion_category, reference_conversion_tag>,
                "A transform iterator can only be applied with a conversion mapping two references");
            return {
                    make_transform((), _ConversionT()),
                    make_transform((), _ConversionT())
            };
        }

        /**
         * @brief Returns the pair <begin, end> transform iterators of a collection, for a given Conversion
         */
        template<typename _ConversionT, typename _SourceCollection>
        std::pair<slam::transform_iterator<_ConversionT,
            typename _SourceCollection::const_iterator,
            typename _SourceCollection::const_iterator::value_type,
            typename _ConversionT::value_type>,
            slam::transform_iterator<_ConversionT,
            typename _SourceCollection::const_iterator,
            typename _SourceCollection::const_iterator::value_type,
            typename _ConversionT::value_type>> make_transform_collection(const _SourceCollection& collection,
                _ConversionT) {
            static_assert(std::is_same_v<typename _ConversionT::conversion_category, reference_conversion_tag>,
                "A transform iterator can only be applied with a conversion mapping two references");
            return {
                    make_transform((), _ConversionT()),
                    make_transform((), _ConversionT())
            };
        }

2. Code analysis

Code parsing: transform_iterator

This code defines a **transform_iterator(transform iterator)**, it passes the value of an iterator throughUnaryFunction(Unary function) converts to different types of values, thus providing a way to convert values ​​during iteration.

1. Transform_iterator class analysis

This class inherits from __composition_iterator, which is a generic iterator, and its core functions are:

  • Stores a basic iterator (_SourceIteratorT)
  • Store a conversion function (_UnaryFuncT)
  • In operator*() and operator->(), apply the conversion function

1.1 The main member of transform_iterator

template<class _UnaryFuncT, class _SourceIteratorT, class _SourceValueT, class _ValueT>
class transform_iterator :
    public __composition_iterator<transform_iterator<_UnaryFuncT, _SourceIteratorT, _SourceValueT, _ValueT>,
    _SourceIteratorT, _SourceValueT> {
  • _UnaryFuncT: A unary function (such as a lambda, functor, or function pointer) used to convert values.
  • _SourceIteratorT: Source iterator type (such as std::vector<int>::iterator).
  • _SourceValueT: The value type of the source iterator.
  • _ValueT: The type of the converted value.

1.2 Main type definition

using __parent_t = __composition_iterator<transform_iterator<_UnaryFuncT, _SourceIteratorT, _SourceValueT, _ValueT>, 
                _SourceIteratorT, _SourceValueT>;

typedef convert_pointer_t<_SourceIteratorT, _ValueT> __pointer_t;
typedef std::iterator_traits<__pointer_t> __std_iterator_traits;
  • __parent_t: Inherited from__composition_iterator, encapsulates basic iterator functions.
  • __pointer_t: Used to obtain the pointer_ValueTpointer type.
  • __std_iterator_traits: used to extract standard iteratorsvalue_typepointerreferenceetc.

1.3 Types required by the iterator

typedef typename _SourceIteratorT::iterator_category iterator_category;
typedef typename _SourceIteratorT::difference_type difference_type;
typedef typename __std_iterator_traits::value_type value_type;
typedef typename __std_iterator_traits::pointer pointer;
typedef typename __std_iterator_traits::reference reference;

These types are the basic types that standard iterators need to provide.

2. The constructor of transform_iterator

transform_iterator() : __parent_t() {};
  • Default constructor, create emptytransform_iterator
transform_iterator(_SourceIteratorT const& it, _UnaryFuncT f) : func(f), __parent_t(it) {}
  • passit(source iterator) andf(Conversion function) Initialization.
explicit transform_iterator(_SourceIteratorT const& it) : __parent_t(it) {};
  • Initialization using only source iterator, the conversion function is not provided.
transform_iterator(const transform_iterator& other) : __parent_t(other.source_it), func() {}
  • Copy the constructor.
transform_iterator(transform_iterator&& other) : __parent_t(other.source_it), func() {
    this->source_it = other.source_it;
}
  • Move the constructor.

3. Overload operators

3.1 operator* (dereference operator)

inline reference operator*() const { return func(*this->source_it); }
  • passfuncrightsource_itThe value pointed to is converted and returns the result.

3.2 operator-> (pointer access operator)

inline pointer operator->() const { return &func(*this->source_it); }
  • Calculate the converted value and return the pointer.

3.3 operator[] (random access)

template<typename ReferenceT = reference>
inline std::enable_if_t<std::is_same_v<ReferenceT, reference> &&
    std::is_same_v<iterator_category, std::random_access_iterator_tag>, ReferenceT>
    operator[](difference_type __n) const {
    static_assert(std::is_same_v<iterator_category, std::random_access_iterator_tag>);
    return func(this->source_it[__n]);
}
  • Only when the iterator supports random access, it is allowedoperator[]

4. make_transform function

This function is used to createtransform_iteratorObject, and according_ConversionTAutomatically deduce types.

template<typename _ConversionT, typename _SourceIteratorT>
slam::transform_iterator<_ConversionT, _SourceIteratorT, 
    typename _SourceIteratorT::value_type, typename _ConversionT::value_type>
    make_transform(_SourceIteratorT it, _ConversionT) {
    static_assert(std::is_same_v<typename _ConversionT::conversion_category, reference_conversion_tag>,
        "A transform iterator can only be applied with a conversion mapping two references");
    return slam::transform_iterator<_ConversionT, _SourceIteratorT, 
        typename _SourceIteratorT::value_type, typename _ConversionT::value_type>(it);
}
  • _ConversionT: The conversion logic must be a reference_conversion_tag.
  • _SourceIteratorT: The iterator type of the source container.
  • typename _SourceIteratorT::value_type: source data type.
  • typename _ConversionT::value_type: converted data type.

5. make_transform_collection

This function is used to createtransform_iteratorIterate over the entire collection.

5.1 Unconventional version

template&lt;typename _ConversionT, typename _SourceCollection&gt;
std::pair&lt;slam::transform_iterator&lt;_ConversionT,
    typename _SourceCollection::iterator,
    typename _SourceCollection::iterator::value_type,
    typename _ConversionT::value_type&gt;,
    slam::transform_iterator&lt;_ConversionT,
    typename _SourceCollection::iterator,
    typename _SourceCollection::iterator::value_type,
    typename _ConversionT::value_type&gt;&gt; 
    make_transform_collection(_SourceCollection&amp; collection, _ConversionT) {
    static_assert(std::is_same_v&lt;typename _ConversionT::conversion_category, reference_conversion_tag&gt;,
        "A transform iterator can only be applied with a conversion mapping two references");
    return {
        make_transform((), _ConversionT()),
        make_transform((), _ConversionT())
    };
}
  • Create transform_iterator for begin and end.

5.2 const version

template&lt;typename _ConversionT, typename _SourceCollection&gt;
std::pair&lt;slam::transform_iterator&lt;_ConversionT,
    typename _SourceCollection::const_iterator,
    typename _SourceCollection::const_iterator::value_type,
    typename _ConversionT::value_type&gt;,
    slam::transform_iterator&lt;_ConversionT,
    typename _SourceCollection::const_iterator,
    typename _SourceCollection::const_iterator::value_type,
    typename _ConversionT::value_type&gt;&gt; 
    make_transform_collection(const _SourceCollection&amp; collection, _ConversionT) {
    return {
        make_transform((), _ConversionT()),
        make_transform((), _ConversionT())
    };
}
  • Suitable forconstContainer.

Summarize

  • transform_iteratorWrapping the original iterator and applying the conversion function when accessed_UnaryFuncT
  • operator*()andoperator->()Apply conversion logic.
  • make_transformCreatetransform_iterator
  • make_transform_collectionCreate the entire collectiontransform_iteratorbegin()andend())。

This pattern is suitable for lazy loading transformations, avoiding explicit creation of new data structures and improving efficiency.

This is the end of this article about the use of C++ transformation iterator. For more related content on the use of C++ transformation iterator, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!