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;
}