Introduction

The range-based for loops in C++11 allow to execute a for loop over a range (without using an index or an iterator).

std::vector<int> v = {1, 2, 3};
for(auto const e : v)
{
   std::cout << e << std::endl;
}

This is actually just syntactic sugar and the compiler transforms it into the following:
auto && __range = v;
for (auto __begin = begin(v), __end = end(v); __begin != __end; ++__begin)
{ 
   auto const e = *__begin; 
   std::cout << e << std::endl;
} 

As you can see, in order to iterate over a range/collection it is necessary to have a begin() and end() function that take the range as argument that return an object (iterator) that implements operator!=, operator++ and operator*.

Note: this is a simplification and for the details see Range-based for loop.

MFC Collections

MFC provides a set of collections, some of them template-based, and some of them non-template based. These collections cover arrays, lists and maps.

Template collections
Arrays Lists Maps
CArray CList CMap
CTypedPtrArray CTypedPtrList CTypedPtrMap

Non-template collections
Arrays Lists Maps
CObArray CObList CMapPtrToWord
CByteArray CPtrList CMapPtrToPtr
CDWordArray CStringList CMapStringToOb
CPtrArray CMapStringToPtr
CStringArray CMapStringToString
CWordArray CMapWordToOb
CUIntArray CMapWordToPtr


It is not possible to use these collections with range-based for loops. If you compile the following code it will fail:

void func(CStringArray const & arr)
{
   for(auto const & str : arr)
   {
      // do something with str
   }
}

1>error C3312: no callable 'begin' function found for type 'CStringArray'
1>error C3312: no callable 'end' function found for type 'CStringArray'

The reasons is there are no begin() and end() functions for these types,

MFC Collections Utilities Library

The library enables the use of all the MFC collections (both template and non-template) by defining appropriate iterator types and begin() and end() functions so that the code the compiled produces from a range-base for loop can execute successfully.

The library is composed of a single header, called mfciterators.h. You need to include this into all your source files where you want to use the range-based for loops with the MFC collections.

For maps you get access to the content through a key-value pair that has two fields: key and value.

Examples

Arrays
CStringArray arr;
arr.Add("this");
arr.Add("is");
arr.Add("a");
arr.Add("sample");

for(auto & s : arr)
{
   s.MakeUpper();
}

CArray<int> arr;
arr.Add(1);
arr.Add(2);
arr.Add(3);
arr.Add(4);

for(auto const n : arr)
{
   std::cout << n << std::endl;
}

Lists
class CFoo
{
public:
   int value;

   CFoo(int const v): value(v) {}
};

CTypedPtrList<CPtrList, CBar*> ptrlist;
ptrlist.AddTail(new CFoo(1));
ptrlist.AddTail(new CFoo(2));
ptrlist.AddTail(new CFoo(3));

for(auto & o : ptrlist)
   o->value *= 2;

CList<int> list;
list.AddTail(1);
list.AddTail(2);
list.AddTail(3);

auto const & clist = list;
for(auto const n : clist)
{
   std::cout << n << std::endl;
}

Maps
CMap<int, int, CString, CString> map;

map.SetAt(1, "one");
map.SetAt(2, "two");
map.SetAt(3, "three");

for(auto & kvp : map)
{
   kvp.value.MakeUpper();
}

for(auto const & kvp : map)
{
   CString temp;
   temp.Format("key=%d, value=%s", kvp.key, kvp.value);
}

CTypedPtrMap<CMapWordToPtr, WORD, CFoo*> map;

map.SetAt(1, new CFoo(1));
map.SetAt(2, new CFoo(2));
map.SetAt(3, new CFoo(3));

// do something with map

for(auto & kvp : map)
{
   delete kvp.value;
}

Last edited Oct 28, 2014 at 9:35 PM by MariusBancila, version 8