避免通用容器中 begin() 和 end() 函数的重复代码

Avoiding duplicate code for begin() and end() functions in generic containers

本文关键字:函数 end 代码 begin      更新时间:2023-10-16
有几个

类似的线程Q1或Q2与此线程相似,但不完全是。

问题只是以优雅的方式编写以下代码,没有代码重复:

template <typename T, class Container = std::vector<T> >
class container{
    iterator begin(){
        return iterator(data_.begin(), 1);
    }
    const_iterator begin() const{
        return const_iterator(data_.begin(), 1);
    }
    Container data_;
};

Q2 有一种优雅的方法,可以避免具有完全相同签名的 const 和非 const 函数的代码重复。然而,这里的情况并非如此,因为没有将const_iterator转换为迭代器的转换。

Q1 提供了一种使用模板的好方法,但是,一旦容器是一个类,begin_impl 函数就会变得static,同时friend

我想出的最优雅的代码是:

template <T>
class container{
        template< typename I, typename C >
        static I begin_impl( C & c ){
            return I(data_.begin(), 1);
        }
        template< typename I, typename C >
        friend I container<T>::begin_impl( C & c );
        iterator begin(){
            return container<T>::template begin_impl< iterator >( *this );
        }
        const_iterator begin() const{
            return container<T>::template begin_impl< const_iterator >( *this );
        }
}   

我的问题是,在您看来,这是否是最优雅的方式。如果没有,请建议一些更好的代码。

编辑:我的迭代器实现:

class container{
        template <bool isConst>
        class iterator_ {
        public:
            typedef Container container_type;
            typedef typename Container::value_type value_type; 
            typedef typename Container::difference_type difference_type;
            typedef typename Container::size_type size_type;
            typedef typename Container::reference reference;
            typedef typename Container::const_reference const_reference;
            typedef typename Container::pointer pointer; 
            typedef typename Container::const_pointer const_pointer;
            typedef typename std::forward_iterator_tag iterator_category;
            template<bool isCond, typename cref, typename ref>
            struct IS_CONST_REF{
                typedef ref reference_type;
            };
            template<typename cref, typename ref>
            struct IS_CONST_REF<true, cref, ref>{
                typedef cref reference_type;
            };            
            typedef typename IS_CONST_REF<isConst, const_reference, reference>::reference_type ref;
            template<bool isCond, typename citr, typename itr>
            struct IS_CONST_ITR{
                typedef itr iterator_type;
            };
            template<typename citr, typename itr>
            struct IS_CONST_ITR<true, citr, itr>{
                typedef citr iterator_type;
            };            
            typedef typename IS_CONST_ITR<isConst, typename Container::const_iterator, typename Container::iterator>::iterator_type itr; 
            iterator_()
            :data_(), stepSize_(0){
            }
            iterator_(itr data, difference_type stepSize)
            :data_(data), stepSize_(stepSize){
            }
            iterator_(const iterator_<false>& src)
            :data_(src.getData()), stepSize_(src.getStepSize()){
            }
        [some more code ...] 
        protected:
            itr data_;
            difference_type stepSize_;
        };
        typedef iterator_<true> const_iterator;
        typedef iterator_<false> iterator;
};

呢:

class container{
    iterator begin(){
        return iterator(getStuff());
    }
    const_iterator begin() const{
        return const_iterator(getStuff());
    }
    private:
       Stuff getStuff() const  { [some code here] }
};

如果您有通用代码。
将其移动到执行该工作的私有方法。

好的,显然这仍然是最佳答案:

template <T>
class container{
        template< typename I, typename C >
        static I begin_impl( C & c ){
            return I(data_.begin(), 1);
        }
        template< typename I, typename C >
        friend I container<T>::begin_impl( C & c );
        iterator begin(){
            return container<T>::template begin_impl< iterator >( *this );
        }
        const_iterator begin() const{
            return container<T>::template begin_impl< const_iterator >( *this );
        }
}