ThamP
ThamP

Reputation: 669

How do I create a map with iterator values?

I am trying to define a class with a map of K -> pair of V and iterator of a list of K. This is to implement LRU cache. I got this working with decltype:

template <typename K, typename V> class LRUCache {
  std::list<K> q;
  typedef decltype(q.begin()) Iterator;

  typedef std::pair<V, Iterator> Node;

  int max_size;
  std::map<const K, Node> m;
}

However, I am not satisfied with using decltype and it all seems brittle when I try to use it. What would be the canonical way of doing this?

Upvotes: 1

Views: 494

Answers (3)

ThamP
ThamP

Reputation: 669

To add to the answers of others - the std::list<K>::iterator is a dependent type and C++ requires us to use typename in front of it.

The reason for this is that the compiler doesn't know whether ::iterator is a type, so it needs a hint with typename.

Another way of dealing with the original issue is to use using template, similar to the way some of <type_traits> are defined in C++14. We can define:

template <typename T> using ListIterator = typename std::list<T>::iterator;

Now, we can simply use ListIterator<K> in the LRUCache code:

template <typename K, typename V> class LRUCache {
  using Node = std::pair<V, ListIterator<K>>;
  std::list<K> q;      
  std::map<const K, Node> m;
  int max_size;
}

Upvotes: 0

Zereges
Zereges

Reputation: 5209

I quite do not like old fashioned way of using typedef, since it seems to use reverse syntax for declaring stuff. You are also using int i = 5 and not int 5 i. (Not only) for this, new usage of using was introduced.

using Iterator = decltype(a.begin());

If you do not like decltype, you can use std::list<K>::iterator, but because K is template parameter, std::list<K> is dependent name and needs to be prefixed with typename.

using Iterator = typename std::list<K>::iterator;

Or with old fashioned typedef

typedef typename std::list<K>::iterator Iterator;

Upvotes: 1

midor
midor

Reputation: 5557

The type of the iterator is

std::list<K>::iterator

If you want to use it, you have to use a typename in front of it, or alias it first with a

using iterator = typename std::list<K>::iterator;

However, using decltype there seems to be a perfectly valid use of it, if you can be sure everyone calling this code has c++11 or later.

Upvotes: 0

Related Questions