How can I return `map<K, V>::iterator`? (`map` class extends `std::map`)
You could return a std::map<K,V>::iterator
. This would make your code compile, but the iterator would be invalid. get_value
returns a copy, m
is local to at_index
and gets destroyed when the function returns.
Inheriting publicly from standard containers is rarely a good idea. Standard containers are not made to be inherited from (eg they do not have a virtual destructor). You can write at_index
as an algorithm:
#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";
}
However, a std::map
isnt meant to be accessed by index. It is rather expensive to advance a maps iterator. If you want a container of key-value pairs that you can access by index, consider to use a std::vector<std::pair<K,V>>
instead.
Ignoring the real problems with the code (deriving from standard containers is not recommended and at_index
returns a dangling iterator to the local object m
) to get the code to compile you have two options.
- within a class you don't need to prefix members of the class with the class name. As
iterator
isn't a class member you need to add it first then an unqualifiediterator
will work:
using iterator = typename std::map<K, V>::iterator;
iterator at_index(int index)
- You can just use
std::map::iterator
directly:
typename std::map<K, V>::iterator at_index(int index)
If what you're actually trying to do is get the ith item in a std::map
this will work:
#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;
}