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_ValueT
pointer type. -
__std_iterator_traits
: used to extract standard iteratorsvalue_type
、pointer
、reference
etc.
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 empty
transform_iterator
。
transform_iterator(_SourceIteratorT const& it, _UnaryFuncT f) : func(f), __parent_t(it) {}
- pass
it
(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); }
- pass
func
rightsource_it
The 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 allowed
operator[]
。
4. make_transform function
This function is used to createtransform_iterator
Object, and according_ConversionT
Automatically 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_iterator
Iterate over the entire collection.
5.1 Unconventional version
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()) }; }
- Create transform_iterator for begin and end.
5.2 const version
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) { return { make_transform((), _ConversionT()), make_transform((), _ConversionT()) }; }
- Suitable for
const
Container.
Summarize
-
transform_iterator
Wrapping the original iterator and applying the conversion function when accessed_UnaryFuncT
。 -
operator*()
andoperator->()
Apply conversion logic. -
make_transform
Createtransform_iterator
。 -
make_transform_collection
Create the entire collectiontransform_iterator
(begin()
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!