Click to See Complete Forum and Search --> : generic lookup using STL map


wayne66
March 8th, 2008, 08:34 PM
The STL map's find method returns an iterator which is tedious
to program with so I decided to write a templated lookup
function as follows:

//
// Generic function that returns val associated with key
// in given map. It is assumed that the key *will* be found.
//
template <class KEY, class VAL>
VAL lookup(map<KEY,VAL>& m, KEY key) {
map<KEY,VAL>::iterator iter = m.find(key);
assert (iter != m.end());
return iter->second;
}

I have trouble getting instances of this to compile via g++.
Here is a small program that demos the problem:

#include <map>
#include <iostream>

using namespace std;

template <class KEY, class VAL>
VAL lookup(map<KEY,VAL>& m, KEY key) {
map<KEY,VAL>::iterator iter = m.find(key);
assert (iter != m.end());
return iter->second;
}

int main() {
map<int,int> m;
m[1] = 100;
m[2] = 200;
int n = lookup(m, 1);
cout << n << endl;
return 0;
}

Here are the error messages.

$ g++ lookup.cpp -o lookup
lookup.cpp: In function ‘VAL lookup(std::map<KEY, VAL, std::less<_Key>, std::allocator<std::pair<const _Key, _Tp> > >&, KEY)’:
lookup.cpp:8: error: expected `;' before ‘iter’
lookup.cpp:9: error: ‘iter’ was not declared in this scope
lookup.cpp: In function ‘VAL lookup(std::map<KEY, VAL, std::less<_Key>, std::allocator<std::pair<const _Key, _Tp> > >&, KEY) [with KEY = int, VAL = int]’:
lookup.cpp:17: instantiated from here
lookup.cpp:8: error: dependent-name ‘std::map<KEY,VAL,std::less<_Key>,std::allocator<std::pair<const _Key, _Tp> > >::iterator’ is parsed as a non-type, but instantiation yields a type
lookup.cpp:8: note: say ‘typename std::map<KEY,VAL,std::less<_Key>,std::allocator<std::pair<const _Key, _Tp> > >::iterator’ if a type is meant

If you want to see how I am using this in a larger context see
http://ezekiel.vancouver.wsu.edu/~cs548/projects/mesh/Mesh.cpp

-much thanks.
--wayne

Paul McKenzie
March 8th, 2008, 08:42 PM
The STL map's find method returns an iterator which is tedious to program with so I decided to write a templated lookup
function as follows: Please use code tags, and get rid of the smilies in your post.

template <class KEY, class VAL>
VAL lookup(map<KEY,VAL>& m, KEY key)
{
typename map<KEY,VAL>::iterator iter = m.find(key);
assert (iter != m.end());
return iter->second;
}

Regards,

Paul McKenzie

Lindley
March 8th, 2008, 09:06 PM
This code is going to give you problems if you try to use it with a const map.

Also, consider returning by reference rather than by value.

NMTop40
March 9th, 2008, 05:26 AM
The assert is probably not a good way to handle not-found, unless you can be sure that you are never going to look up a key that is not there, i.e. it would be a programming error to do so.

My own preferencial way to do it is:

template < typename KEY, typename VAL >
bool map_lookup( const std::map< KEY, VAL > & m, const KEY & k, VAL & v )
{
typename std::map< KEY, VAL >::const_iterator it = m.find( k );
if ( it != m.end() )
{
v = it->second;
return true;
}
else
{
return false;
}
}

wayne66
March 9th, 2008, 02:24 PM
Wow. Thanks for all of the quick and useful replies.
Now I know *yet another* esoteric detail of C++ -- the
use of typename for template dependent types.

jlou
March 10th, 2008, 06:01 PM
If you're going to assume the key is always there, why not just use operator[]?

Otherwise I like NMTop40's example.