我怎样才能 return `map<K, V>::iterator`? (`map` class 扩展了 `std::map`)
How can I return `map<K, V>::iterator`? (`map` class extends `std::map`)
我正在制作扩展 std::map
的自定义地图 class (kc::map
),我想添加 at_index()
,我需要 return map<K, V>::iterator
。但是当我returnmap<K, V>
的时候出现这个错误:error: invalid use of incomplete type ‘class kc::map<K, V>’
:
namespace kc
{
template<typename K, typename V> class map : public std::map<K, V>
{
public:
using std::map<K, V>::map;
map<K, V> get_value()
{
return *this;
}
map<K, V>::iterator at_index(int index)
{
map<K, V> m = get_value();
for (int i = 0; i < index; i++)
{
m.erase(m.begin());
}
return m.begin();
}
};
};
你可以 return 一个 std::map<K,V>::iterator
。这将使您的代码编译,但迭代器将无效。 get_value
returns 副本,m
是 at_index
的本地副本,并在函数 returns.
时被销毁
从标准容器公开继承很少是个好主意。标准容器不是用来继承的(例如,它们没有虚拟析构函数)。你可以把at_index
写成一个算法:
#include <map>
#include <iostream>
template <typename IT>
IT get_at_index(IT begin,IT end,unsigned index){
if (std::distance(begin,end) < index) return end;
return std::next(begin,index);
}
int main() {
std::map<int,int> m{{1,1},{2,2},{3,3}};
auto it = get_at_index(m.begin(),m.end(),1);
if (it != m.end()) std::cout << it->first << " " << it->second << "\n";
it = get_at_index(m.begin(),m.end(),5);
if (it == m.end()) std::cout << "index 5 is out of range\n";
}
但是,std::map
并不意味着可以通过索引访问。推进地图迭代器是相当昂贵的。如果您想要一个可以通过索引访问的键值对容器,请考虑使用 std::vector<std::pair<K,V>>
。
忽略代码的真正问题(不推荐从标准容器派生,at_index
returns 到本地对象的悬空迭代器 m
)来编译代码你有两个选择。
- 在 class 中,您不需要在 class 的成员前面加上 class 名称。由于
iterator
不是 class 成员,您需要先添加它,然后不合格的 iterator
才会起作用:
using iterator = typename std::map<K, V>::iterator;
iterator at_index(int index)
- 你可以直接使用
std::map::iterator
:
typename std::map<K, V>::iterator at_index(int index)
如果您实际上想做的是获取 std::map
中的第 i 个项目,这将有效:
#include <map>
#include <stdexcept>
#include <iostream>
namespace kc
{
template<typename K, typename V> class map
{
private:
std::map<K, V> impl;
public:
using iterator = typename std::map<K, V>::iterator;
using value_type = typename std::map<K, V>::value_type;
std::pair<iterator, bool> insert( const value_type& value )
{
return impl.insert(value);
}
iterator at_index(int index)
{
if (index >= impl.size())
{
throw std::invalid_argument("index out of range");
}
auto it = impl.begin();
std::advance(it, index);
return it;
}
};
};
int main()
{
kc::map<int, int> m;
m.insert({1, 1});
m.insert({2, 2});
m.insert({3, 3});
std::cout << m.at_index(2)->second;
}
我正在制作扩展 std::map
的自定义地图 class (kc::map
),我想添加 at_index()
,我需要 return map<K, V>::iterator
。但是当我returnmap<K, V>
的时候出现这个错误:error: invalid use of incomplete type ‘class kc::map<K, V>’
:
namespace kc
{
template<typename K, typename V> class map : public std::map<K, V>
{
public:
using std::map<K, V>::map;
map<K, V> get_value()
{
return *this;
}
map<K, V>::iterator at_index(int index)
{
map<K, V> m = get_value();
for (int i = 0; i < index; i++)
{
m.erase(m.begin());
}
return m.begin();
}
};
};
你可以 return 一个 std::map<K,V>::iterator
。这将使您的代码编译,但迭代器将无效。 get_value
returns 副本,m
是 at_index
的本地副本,并在函数 returns.
从标准容器公开继承很少是个好主意。标准容器不是用来继承的(例如,它们没有虚拟析构函数)。你可以把at_index
写成一个算法:
#include <map>
#include <iostream>
template <typename IT>
IT get_at_index(IT begin,IT end,unsigned index){
if (std::distance(begin,end) < index) return end;
return std::next(begin,index);
}
int main() {
std::map<int,int> m{{1,1},{2,2},{3,3}};
auto it = get_at_index(m.begin(),m.end(),1);
if (it != m.end()) std::cout << it->first << " " << it->second << "\n";
it = get_at_index(m.begin(),m.end(),5);
if (it == m.end()) std::cout << "index 5 is out of range\n";
}
但是,std::map
并不意味着可以通过索引访问。推进地图迭代器是相当昂贵的。如果您想要一个可以通过索引访问的键值对容器,请考虑使用 std::vector<std::pair<K,V>>
。
忽略代码的真正问题(不推荐从标准容器派生,at_index
returns 到本地对象的悬空迭代器 m
)来编译代码你有两个选择。
- 在 class 中,您不需要在 class 的成员前面加上 class 名称。由于
iterator
不是 class 成员,您需要先添加它,然后不合格的iterator
才会起作用:
using iterator = typename std::map<K, V>::iterator;
iterator at_index(int index)
- 你可以直接使用
std::map::iterator
:
typename std::map<K, V>::iterator at_index(int index)
如果您实际上想做的是获取 std::map
中的第 i 个项目,这将有效:
#include <map>
#include <stdexcept>
#include <iostream>
namespace kc
{
template<typename K, typename V> class map
{
private:
std::map<K, V> impl;
public:
using iterator = typename std::map<K, V>::iterator;
using value_type = typename std::map<K, V>::value_type;
std::pair<iterator, bool> insert( const value_type& value )
{
return impl.insert(value);
}
iterator at_index(int index)
{
if (index >= impl.size())
{
throw std::invalid_argument("index out of range");
}
auto it = impl.begin();
std::advance(it, index);
return it;
}
};
};
int main()
{
kc::map<int, int> m;
m.insert({1, 1});
m.insert({2, 2});
m.insert({3, 3});
std::cout << m.at_index(2)->second;
}