Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 只为容器提供常量迭代器有意义吗?_C++_C++11_Iterator - Fatal编程技术网

C++ 只为容器提供常量迭代器有意义吗?

C++ 只为容器提供常量迭代器有意义吗?,c++,c++11,iterator,C++,C++11,Iterator,我有一个类似于下一个的容器: class MySpecialContainer { std::vector<std::tuple<InternalType, Type1, Type2>> _vec; }; 正如您所看到的,这种方法有几个限制,比如不能在子范围上迭代,或者不能使用非变异std::algorithms 考虑到MySpecialContainer元素从外部是不可变的,从逻辑上考虑,只为其提供const\u迭代器有意义吗 如果第一个问题的答案是肯定的,那

我有一个类似于下一个的容器:

class MySpecialContainer
{
    std::vector<std::tuple<InternalType, Type1, Type2>> _vec;
};
正如您所看到的,这种方法有几个限制,比如不能在子范围上迭代,或者不能使用非变异
std::algorithms

考虑到
MySpecialContainer
元素从外部是不可变的,从逻辑上考虑,只为其提供
const\u迭代器有意义吗

如果第一个问题的答案是肯定的,那么最好是

  • \u vec
    分为两个容器,一个用于
    InternalType
    ,另一个用于
    std::pair
    ,保持它们同步,只需返回第二个向量的
    常量迭代器即可

  • 保持向量现在的状态,并创建一个自定义迭代器,该迭代器仅公开
    consttype1
    consttype2


  • 一种选择是公开迭代器,该迭代器只允许访问元素的某些字段,例如:

    #include <vector>
    #include <tuple>
    #include <boost/iterator/transform_iterator.hpp>
    
    struct Type1 {};
    struct Type2 {};
    struct InternalType {};
    
    class MySpecialContainer
    {
        typedef std::vector<std::tuple<InternalType, Type1, Type2>> Vec;
        Vec _vec;
    
        struct Extractor
        {
            std::tuple<Type1&, Type2&> operator()(Vec::value_type& t) const {
                return std::tie(std::get<1>(t), std::get<2>(t));
            }
    
            std::tuple<Type1 const&, Type2 const&> operator()(Vec::value_type const& t) const {
                return std::tie(std::get<1>(t), std::get<2>(t));
            }
        };
    
    public:
        typedef boost::transform_iterator<Extractor, Vec::iterator> iterator;
        typedef boost::transform_iterator<Extractor, Vec::const_iterator> const_iterator;
    
        iterator begin() { return iterator{_vec.begin()}; }
        iterator end() { return iterator{_vec.end()}; }
        const_iterator begin() const { return const_iterator{_vec.begin()}; }
        const_iterator end() const { return const_iterator{_vec.end()}; }
    };
    
    int main() {
        MySpecialContainer c;
        for(auto x : c) {
        }
    }
    
    #包括
    #包括
    #包括
    结构类型1{};
    结构类型2{};
    结构内部类型{};
    类MySpecialContainer
    {
    typedef std::向量向量;
    Vec(u-Vec),;
    结构提取器
    {
    std::tuple operator()(Vec::value\u type&t)常量{
    返回std::tie(std::get(t),std::get(t));
    }
    std::tuple operator()(Vec::value_type const&t)const{
    返回std::tie(std::get(t),std::get(t));
    }
    };
    公众:
    typedef boost::transform_迭代器迭代器;
    typedef boost::transform_iterator const_iterator;
    迭代器begin(){返回迭代器{u vec.begin()};}
    迭代器end(){返回迭代器{u vec.end()};}
    常量迭代器begin()常量{返回常量迭代器{vec.begin()};}
    常量迭代器end()常量{返回常量迭代器{u vec.end()};}
    };
    int main(){
    我的特殊容器c;
    用于(自动x:c){
    }
    }
    

    请注意,通过非常量迭代器,您仍然可以更新公开的值,因为trasform迭代器返回一个引用元组。

    只公开常量迭代器就可以了。标准中甚至有优先权,因为
    std::set
    有效地做到了这一点。从技术上讲,
    iterator
    const\u iterator
    可以是不同的类型,但是不允许通过任何一种类型的迭代器修改元素,因为这可能会破坏
    集的不变量

    使用合适的类而不是
    元组
    (因此您可以通过访问者公开
    Type1
    Type2
    )@Jarod42第二个问题的解决方案非常好!谢谢!@Felics回答你的第一个问题,是的,当你想防止类外的修改时,为封装的向量提供常量迭代器是最简单的解决方案。作为一个额外的奖励,只允许返回常量迭代器,你正在传达你对membe的意图r也是。在标准库中是否有一个等价的
    boost::transform\u iterator
    呢?@Felics-Nope,标准库非常简单。这就是boost存在的原因……你可以派生
    std::vector::iterator
    并重写
    操作符*
    操作符->
    来进行转换。谢谢!我会投票给你r回答,因为这是一种关于如何提供迭代器的非常有趣的方法。我不会接受它,因为它没有回答我关于只提供
    const_迭代器
    @Felics的问题。好吧,您可以省略begin/end的非const版本。它们在这里展示,可以为您的元素的某些成员提供可修改的视图这是第一个问题的答案,第二个问题的答案请查看Maxim Yegorushkin的答案。
    #include <vector>
    #include <tuple>
    #include <boost/iterator/transform_iterator.hpp>
    
    struct Type1 {};
    struct Type2 {};
    struct InternalType {};
    
    class MySpecialContainer
    {
        typedef std::vector<std::tuple<InternalType, Type1, Type2>> Vec;
        Vec _vec;
    
        struct Extractor
        {
            std::tuple<Type1&, Type2&> operator()(Vec::value_type& t) const {
                return std::tie(std::get<1>(t), std::get<2>(t));
            }
    
            std::tuple<Type1 const&, Type2 const&> operator()(Vec::value_type const& t) const {
                return std::tie(std::get<1>(t), std::get<2>(t));
            }
        };
    
    public:
        typedef boost::transform_iterator<Extractor, Vec::iterator> iterator;
        typedef boost::transform_iterator<Extractor, Vec::const_iterator> const_iterator;
    
        iterator begin() { return iterator{_vec.begin()}; }
        iterator end() { return iterator{_vec.end()}; }
        const_iterator begin() const { return const_iterator{_vec.begin()}; }
        const_iterator end() const { return const_iterator{_vec.end()}; }
    };
    
    int main() {
        MySpecialContainer c;
        for(auto x : c) {
        }
    }