Lookup in std::map

The STL is a very powerful and highly-customizable C++ library (for example, you can provide custom allocators for its containers), but my impression is that sometimes the public interfaces of some classes lack some useful and convenient methods.

One example is std::map: both ATL’s CAtlMap and .NET BCL’s Dictionary classes offer a convenient lookup method (CAtlMap::Lookup and Dictionary.TryGetValue respectively).

Unfortunately, there is nothing similar in STL’s std::map. The logic flow of operations for this class is:

1. call the map::find method passing the key; this method returns an iterator;

2. if the returned iterator equals map::end, the key is not contained in the map;

3. if the returned iterator is valid, the value associated with the given key can be found in iterator->second.

That’s not very intuitive and convenient (IMHO). Fortunately, we can embedd this sequence of operations in a template function, as follows:

//------------------------------------------------------------------------
// FUNCTION: lookup
//
// DESCRIPTION:
// Given an instance of std::map, this function checks if the specified key
// is contained in the map.
// If so, the function copies the value associated with the key in 'value'
// parameter, and returns true.
// If the key is not contained in the map, the function returns false
// (and the 'value' parameter is undefined).
//------------------------------------------------------------------------
template <class Key, class Value, class Compare, class Allocator>
bool lookup(
  std::map<Key, Value, Compare, Allocator> const& theMap,
  typename std::map<Key, Value, Compare, Allocator>::key_type const& key,
  typename std::map<Key, Value, Compare, Allocator>::mapped_type & value
)
{
  // Search for the specified key in the map
  auto it = theMap.find(key);
 
  // If the key is not found in the map, just return false
  if (it == theMap.end())
  {
    return false;
  }
 
  // Key found in map.
  // Copy the associated value back to the caller
  value = it->second;
 
  // Key found
  return true;
}

EDIT 2010-12-15: Thanks Stephan ‘STL’ for enlightment on a template argument deduction issue.

EDIT 2017-01-12: Used Auto SyntaxHighlighter for C++ source code.

Some links on writing exception-safe code in C++

I found a very interesting thread on StackOverflow about writing exception safe code in C++:

C++: do you (really) write exception safe code?

The first answer is worth reading.

And, as already written in the aforementioned thread, detailed information on this subject can be found on GotW website, too:

GotW #59: Exception-Safe Class Design, Part 1: Copy Assignment

GotW #60: Exception-Safe Class Design, Part 2: Inheritance

GotW #61: CHALLENGE EDITION: ACID Programming 
 

STL strings are not zero-terminated

In a previous blog post, I listed some advantages (IMHO) of using CString instead of std::string class.

There is another subtle (but important!) point which turns the scales in CString‘s favour: in fact, CString is a C++ class that wraps zero-terminated strings (i.e. the good old C strings), instead it seems that the C++ standard library code wants to pretend that zero-terminated strings do not exist…

Let me show this with a sample code (the full C++ source code is attached to this blog post):

    //

    // Check with CString

    //

    CString str;

    WCHAR * psz = str.GetBuffer(100);

    psz[0] = 0; // …or GetWindowText(hwnd, psz, 100)

    str.ReleaseBuffer();

    psz = NULL; // psz is no more valid

    assert( wcslen(str) == str.GetLength() ); // OK

 

 

 

    //

    // Check with std::string

    //

    std::wstring s;

    s.resize(100);

    s[0] = 0; // …or GetWindowText(hwnd, &s[0], 100)

    assert( wcslen(s.c_str()) == s.length() ); // BANG!

So, basically, we have a situation in which (assuming ‘s‘ is an instance of std::wstring) s.length() and wcslen(s.c_str()) do not return the same value.

Considering that Windows APIs (like say GetWindowText) work with zero-terminated strings, CString seems to me a clear winner as a convenient string class for C++ Win32 programming.