Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.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++_Stl_Iterator_Encapsulation - Fatal编程技术网

C++ 如何使集合迭代器的行为类似于映射迭代器?

C++ 如何使集合迭代器的行为类似于映射迭代器?,c++,stl,iterator,encapsulation,C++,Stl,Iterator,Encapsulation,我有一个类Foo,它包含一个map,并提供begin()和end()函数来迭代它: class Foo { typedef std::map<int, double> Container; typedef Container::const_iterator const_iterator; Container c_; public: const_iterator begin() const { return c_.begin(); } const_iterator

我有一个类
Foo
,它包含一个
map
,并提供
begin()
end()
函数来迭代它:

class Foo {
  typedef std::map<int, double> Container;
  typedef Container::const_iterator const_iterator;
  Container c_;
 public:
  const_iterator begin() const { return c_.begin(); }
  const_iterator end() const { return c_.end(); }
  void insert(int i, double d) { c_[i] = d; }
  // ...

};
如何在
Foo
类中进行这些更改

换句话说,我如何提供一个
Foo::const_迭代器
,使新的内部
std::set::const_迭代器
能够像旧的
std::map::const_迭代器一样工作


更新:我想摆脱
映射的原因是内存效率。我有数以百万计的
Foo
实例,无法在其中存储
double

operator int()(const std::pair<int, double>& p) const {
    return p.first;
}
运算符int()(const std::pair&p)const{
返回p.first;
}
也许在某个包装内?

会使用

std::set<std::pair<int, double> >

也许您可以定义一个
fake\u pair
类来实现
第一个
第二个
,并将
放在
Foo

像这样的怎么样

#include <iostream>
#include <map>
#include <set>

struct Funky
{
    int first;
    static const double second;

    Funky(int i)
    :   first(i)
    {}
};

const double Funky::second = 0.0;

bool operator<(const Funky& lhs, const Funky& rhs)
{
    return lhs.first < rhs.first;
}

class Foo
{
private:
    //std::map<int,double> m_data;
    std::set<Funky> m_data;
public:
    //typedef std::map<int,double>::const_iterator const_iterator;
    typedef std::set<Funky>::const_iterator const_iterator;

    const_iterator begin() const
    {
        return m_data.begin();
    }

    const_iterator end() const
    {
        return m_data.end();
    }

    void insert(int i, double d)
    {
        //m_data.insert(std::make_pair(i, d));
        m_data.insert(i);
    }
};

int main()
{
    Foo foo;
    foo.insert(23, 9.0);
    for(Foo::const_iterator it=foo.begin(), iend=foo.end(); it!=iend; ++it)
    {
        std::cout << it->first << ' ' << it->second << '\n';
    }
    return 0;
}
#包括
#包括
#包括
结构时髦
{
int优先;
静态常数双秒;
芬奇(国际一级)
:第一(i)
{}
};
const double Funky::second=0.0;

bool操作符你不能,不能完全。问题是你正在改变你的界面,这总是会破坏你的客户端。我建议您创建两个新函数newBegin和newEnd(或类似函数),它们具有您的新行为。旧界面保持不变,但将其标记为已折旧。这个旧接口的实现可以使用其他接口描述的解决方法之一。

不,我应该这样说:我现在需要
集的原因是我想节省内存。我有数以百万计的
Foo
实例,无法再存储这两个实例了。我更新了答案,添加了一个只需最少额外开销即可实现兼容性的示例。当然,现在获取两个成员中任何一个的地址都是一个坏主意,但是如果遗留代码不依赖它,那么它可能会解决您的问题。老实说,这听起来真是个坏主意。当语义完全改变时,保持合同的兼容性是没有意义的。“KORADRADOLPHP C++从第一天起就一直在做。”但这不是做同样事情的理由。我在开玩笑:在C++中,它是(现在有问题的)设计的一部分。这是一个明显的后果,这是我们可以避免的。向后兼容性是一个pita,只有在绝对必要的情况下才需要做。我要指出的一点是,任何试图改变
it->second
的操作现在都会失败——因此您可能需要去掉const。或者,你可能想让人们知道发生了什么…(我确实认为做这种事情的整个想法是相当不明智的,作为记录…)我不认为重新定义
运算符是完全必要的(而且g++同意)——你为什么不认为呢?顺便说一句,科莫也同意。
#include <iostream>
#include <set>

class Foo {
  typedef std::set<int> Container;
  typedef Container::const_iterator legacy_iterator;
  Container c_;

  // legacy iterator doesn't have a virtual destructor (probably?), shouldn't
  // be a problem for sane usage though
  class compat_iterator : public legacy_iterator {
  public:
     compat_iterator(const legacy_iterator& it) : legacy_iterator(it) {
     }

     const std::pair<int,double> *operator->() const {
        static std::pair<int,double> value;
        value = std::make_pair(**this, 0.0);
        // Not meeting the usual semantics!
        return &value;
     }
  };
 public:
  typedef compat_iterator const_iterator;

  const_iterator begin() const { return c_.begin(); }
  const_iterator end() const { return c_.end(); }

};



int main() {

  Foo foo;
  for(Foo::const_iterator it = foo.begin(); it != foo.end(); ++it) {
     std::cout << it->first << " " << it->second << std::endl;
  }

}
#include <iostream>
#include <map>
#include <set>

struct Funky
{
    int first;
    static const double second;

    Funky(int i)
    :   first(i)
    {}
};

const double Funky::second = 0.0;

bool operator<(const Funky& lhs, const Funky& rhs)
{
    return lhs.first < rhs.first;
}

class Foo
{
private:
    //std::map<int,double> m_data;
    std::set<Funky> m_data;
public:
    //typedef std::map<int,double>::const_iterator const_iterator;
    typedef std::set<Funky>::const_iterator const_iterator;

    const_iterator begin() const
    {
        return m_data.begin();
    }

    const_iterator end() const
    {
        return m_data.end();
    }

    void insert(int i, double d)
    {
        //m_data.insert(std::make_pair(i, d));
        m_data.insert(i);
    }
};

int main()
{
    Foo foo;
    foo.insert(23, 9.0);
    for(Foo::const_iterator it=foo.begin(), iend=foo.end(); it!=iend; ++it)
    {
        std::cout << it->first << ' ' << it->second << '\n';
    }
    return 0;
}