使用自定义迭代器封装地图的容器 class
Container class that encapsulates map with custom iterators
我想制作一个 class 来封装一个 std::map
并充当不同类型的容器,如下所示:
class Item
{
public:
Item(int number, const char *text) :
Number(number),
Text(text)
{}
int Number;
std::string Text;
};
class Container
{
public:
void add(Item item)
{
Map.insert(std::make_pair(item.Number, item.Text));
}
Container::iterator begin();
Container::iterator end();
private:
std::map <int, string> Map;
};
我想这样用,不使用地图的first
和second
:
int main()
{
Container container;
container.add(Item(0, "foo"));
container.add(Item(1, "bar"));
for (auto &elem : container)
{
// elem is an Item
cout << elem.Number << elem.Text << endl;
}
}
我尝试实现一个封装了映射迭代器的自定义迭代器,但我卡在了 ->
运算符上,它必须 return 一个 Item
对象的地址(对吗? ) 没有 Item
对象的地址我可以 return.
你是怎么做到的?
我不确定,但看起来您正在寻找结构化绑定。
类似
std::map<int, std::string> myMap{};
for (const auto &[num, txt] : myMap) {
// elem is an Item
cout << num << ' ' << txt << '\n';
}
请阅读here
但是如果您真的对这种自定义容器的迭代器实现感兴趣,请看下面:
#include <iostream>
#include <string>
#include <map>
#include <iterator>
#include <utility>
#include <type_traits>
using Pair = std::pair<int, std::string>;
using Map = std::map<Pair::first_type, Pair::second_type>;
struct Item {
Pair::first_type number{};
Pair::second_type text{};
};
class Container {
Map data{};
public:
void add(Item item) { data.insert({ item.number, item.text }); }
// Add iterator properties to class ---------------------------------------------------------------
class iterator { // Local class for iterator
Map::iterator iter{}; // This will be the internal iterator
Map::iterator begin{}; // For boundary checking
Map::iterator end{};
Item item;
public: // Define alias names necessary for the iterator functionality
using iterator_category = std::random_access_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = Item;
using pointer = const Item* const;
using reference = Item&;
// Constructor
iterator(const Map::iterator& i, const Map::iterator& ibegin, const Map::iterator& iend) : iter(i), begin(ibegin), end(iend) {};
// Dereferencing
value_type operator *() const { return { iter->first, iter->second }; }
pointer operator ->() { item = { iter->first, iter->second }; return &item; }
// Aithmetic operations
iterator& operator ++() { if (iter != end) ++iter; return *this; }
iterator& operator --() { if (iter != begin) --iter; return *this; }
iterator operator ++(int) { iterator tmp{ *this }; ++iter; return tmp; }
iterator operator --(int) { iterator tmp{ *this }; ++iter; return tmp; }
iterator operator +(const difference_type& n) const { iterator tmp{ *this }; difference_type k{ n }; while (k--)++tmp; return tmp; }
iterator& operator +=(const difference_type& n) { difference_type k{ n }; while (k--)++* this; return *this; };
iterator operator -(const difference_type& n) const { iterator tmp{ *this }; difference_type k{ n }; while (k--)--tmp; return tmp; }
iterator& operator -=(const difference_type& n) { difference_type k{ n }; while (k--)--* this; return *this; };
// Comparison
bool operator != (const iterator& other) const { return iter != other.iter; }
bool operator == (const iterator& other) const { return iter == other.iter; }
bool operator < (const iterator& other) const { return (other - *this) < 0; }
bool operator > (const iterator& other) const { return (other - *this) > 0; }
bool operator <= (const iterator& other) const { return (other - *this) <= 0; }
bool operator >= (const iterator& other) const { return (other - *this) >= 0; }
// Reference and difference. Also very questionable
reference operator[] (const difference_type& n) {
iterator tmp(begin, begin, end);
difference_type k{ n }; while (k--) ++tmp;
item = *tmp;
return item;
}
//Extermely complex and unefficient
difference_type operator-(const iterator& other) const {
difference_type result{};
if (*this != other) {
iterator tmp(iter, begin, end);
while ((tmp.iter != other.iter) and tmp.iter != end) {
++tmp;
++result;
}
if (tmp.iter == end) {
result = 0;
iterator tmpOther(other.iter, other.begin, other.end);
while ((tmpOther.iter != iter) and tmpOther.iter != other.end) {
++tmpOther;
--result;
}
}
}
return result;
}
};
iterator begin() { return iterator(data.begin(), data.begin(), data.end()); }
iterator end() { return iterator(data.end(), data.begin(), data.end()); }
};
// Test Code
int main() {
Container c;
c.add({ 1,"111" });
c.add({ 2,"222" });
c.add({ 3,"333" });
c.add({ 4,"444" });
for (const Item& i : c)
std::cout << i.number << ' ' << i.text << '\n';
}
我想制作一个 class 来封装一个 std::map
并充当不同类型的容器,如下所示:
class Item
{
public:
Item(int number, const char *text) :
Number(number),
Text(text)
{}
int Number;
std::string Text;
};
class Container
{
public:
void add(Item item)
{
Map.insert(std::make_pair(item.Number, item.Text));
}
Container::iterator begin();
Container::iterator end();
private:
std::map <int, string> Map;
};
我想这样用,不使用地图的first
和second
:
int main()
{
Container container;
container.add(Item(0, "foo"));
container.add(Item(1, "bar"));
for (auto &elem : container)
{
// elem is an Item
cout << elem.Number << elem.Text << endl;
}
}
我尝试实现一个封装了映射迭代器的自定义迭代器,但我卡在了 ->
运算符上,它必须 return 一个 Item
对象的地址(对吗? ) 没有 Item
对象的地址我可以 return.
你是怎么做到的?
我不确定,但看起来您正在寻找结构化绑定。
类似
std::map<int, std::string> myMap{};
for (const auto &[num, txt] : myMap) {
// elem is an Item
cout << num << ' ' << txt << '\n';
}
请阅读here
但是如果您真的对这种自定义容器的迭代器实现感兴趣,请看下面:
#include <iostream>
#include <string>
#include <map>
#include <iterator>
#include <utility>
#include <type_traits>
using Pair = std::pair<int, std::string>;
using Map = std::map<Pair::first_type, Pair::second_type>;
struct Item {
Pair::first_type number{};
Pair::second_type text{};
};
class Container {
Map data{};
public:
void add(Item item) { data.insert({ item.number, item.text }); }
// Add iterator properties to class ---------------------------------------------------------------
class iterator { // Local class for iterator
Map::iterator iter{}; // This will be the internal iterator
Map::iterator begin{}; // For boundary checking
Map::iterator end{};
Item item;
public: // Define alias names necessary for the iterator functionality
using iterator_category = std::random_access_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = Item;
using pointer = const Item* const;
using reference = Item&;
// Constructor
iterator(const Map::iterator& i, const Map::iterator& ibegin, const Map::iterator& iend) : iter(i), begin(ibegin), end(iend) {};
// Dereferencing
value_type operator *() const { return { iter->first, iter->second }; }
pointer operator ->() { item = { iter->first, iter->second }; return &item; }
// Aithmetic operations
iterator& operator ++() { if (iter != end) ++iter; return *this; }
iterator& operator --() { if (iter != begin) --iter; return *this; }
iterator operator ++(int) { iterator tmp{ *this }; ++iter; return tmp; }
iterator operator --(int) { iterator tmp{ *this }; ++iter; return tmp; }
iterator operator +(const difference_type& n) const { iterator tmp{ *this }; difference_type k{ n }; while (k--)++tmp; return tmp; }
iterator& operator +=(const difference_type& n) { difference_type k{ n }; while (k--)++* this; return *this; };
iterator operator -(const difference_type& n) const { iterator tmp{ *this }; difference_type k{ n }; while (k--)--tmp; return tmp; }
iterator& operator -=(const difference_type& n) { difference_type k{ n }; while (k--)--* this; return *this; };
// Comparison
bool operator != (const iterator& other) const { return iter != other.iter; }
bool operator == (const iterator& other) const { return iter == other.iter; }
bool operator < (const iterator& other) const { return (other - *this) < 0; }
bool operator > (const iterator& other) const { return (other - *this) > 0; }
bool operator <= (const iterator& other) const { return (other - *this) <= 0; }
bool operator >= (const iterator& other) const { return (other - *this) >= 0; }
// Reference and difference. Also very questionable
reference operator[] (const difference_type& n) {
iterator tmp(begin, begin, end);
difference_type k{ n }; while (k--) ++tmp;
item = *tmp;
return item;
}
//Extermely complex and unefficient
difference_type operator-(const iterator& other) const {
difference_type result{};
if (*this != other) {
iterator tmp(iter, begin, end);
while ((tmp.iter != other.iter) and tmp.iter != end) {
++tmp;
++result;
}
if (tmp.iter == end) {
result = 0;
iterator tmpOther(other.iter, other.begin, other.end);
while ((tmpOther.iter != iter) and tmpOther.iter != other.end) {
++tmpOther;
--result;
}
}
}
return result;
}
};
iterator begin() { return iterator(data.begin(), data.begin(), data.end()); }
iterator end() { return iterator(data.end(), data.begin(), data.end()); }
};
// Test Code
int main() {
Container c;
c.add({ 1,"111" });
c.add({ 2,"222" });
c.add({ 3,"333" });
c.add({ 4,"444" });
for (const Item& i : c)
std::cout << i.number << ' ' << i.text << '\n';
}