$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: nesotto_at_[hidden]
Date: 2007-10-23 16:28:53
Author: nesotto
Date: 2007-10-23 16:28:52 EDT (Tue, 23 Oct 2007)
New Revision: 40381
URL: http://svn.boost.org/trac/boost/changeset/40381
Log:
Shunsuke Sogame's MFC/ATL docs and tests
Added:
   trunk/libs/range/doc/mfc_atl.html   (contents, props changed)
   trunk/libs/range/doc/mfc_atl.rst   (contents, props changed)
   trunk/libs/range/test/atl.cpp   (contents, props changed)
Text files modified: 
   trunk/libs/range/test/mfc.cpp |   769 +++++++++++++++++++++++++++++++++++++-- 
   1 files changed, 714 insertions(+), 55 deletions(-)
Added: trunk/libs/range/doc/mfc_atl.html
==============================================================================
--- (empty file)
+++ trunk/libs/range/doc/mfc_atl.html	2007-10-23 16:28:52 EDT (Tue, 23 Oct 2007)
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
+<title>Boost Range MFC/ATL Extension</title>
+<meta name="author" content="Shunsuke Sogame" />
+<meta name="date" content="26th of May 2006" />
+<meta name="copyright" content="Shunsuke Sogame 2005-2006. Use, modification and distribution is subject to the Boost Software License, Version 1.0 (see LICENSE_1_0.txt)." />
+<style type="text/css">
+
+@import "http://www.boost.org/libs/ptr_container/doc/default.css";
+
+</style>
+</head>
+<body>
+<div class="document" id="boost-range-mfc-atl-extension">
+<h1 class="title"><img alt="Boost" src="http://www.boost.org/libs/ptr_container/doc/boost.png" /> Range MFC/ATL Extension</h1>
+<table class="docinfo" frame="void" rules="none">
+<col class="docinfo-name" />
+<col class="docinfo-content" />
+<tbody valign="top">
+<tr><th class="docinfo-name">Author:</th>
+<td>Shunsuke Sogame</td></tr>
+<tr><th class="docinfo-name">Contact:</th>
+<td><a class="first last reference" href="mailto:mb2act@yahoo.co.jp">mb2act@yahoo.co.jp</a></td></tr>
+<tr><th class="docinfo-name">Date:</th>
+<td>26th of May 2006</td></tr>
+<tr><th class="docinfo-name">Copyright:</th>
+<td>Shunsuke Sogame 2005-2006. Use, modification and distribution is subject to the Boost Software License, Version 1.0 (see <a class="reference" href="http://www.boost.org/LICENSE_1_0.txt">LICENSE_1_0.txt</a>).</td></tr>
+</tbody>
+</table>
+<div class="section">
+<h1><a id="overview" name="overview">Overview</a></h1>
+<p>Boost.Range MFC/ATL Extension provides <a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> support for MFC/ATL collection and string types.</p>
+<pre class="literal-block">
+CTypedPtrArray<CPtrArray, CList<CString> *> myArray;
+...
+BOOST_FOREACH (CList<CString> *theList, myArray)
+{
+    BOOST_FOREACH (CString& str, *theList)
+    {
+        boost::to_upper(str);
+        std::sort(boost::begin(str), boost::end(str));
+        ...
+    }
+}
+</pre>
+<ul class="simple">
+<li><a class="reference" href="#requirements">Requirements</a></li>
+<li><a class="reference" href="#mfc-ranges">MFC Ranges</a></li>
+<li><a class="reference" href="#atl-ranges">ATL Ranges</a></li>
+<li><a class="reference" href="#const-ranges">const Ranges</a></li>
+<li><a class="reference" href="#references">References</a></li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="requirements" name="requirements">Requirements</a></h1>
+<ul class="simple">
+<li><a class="reference" href="http://www.boost.org/">Boost C++ Libraries Version 1.34.0</a> or later (no compilation required)</li>
+<li>Visual C++ 7.1 or Visual C++ 8.0</li>
+</ul>
+</div>
+<div class="section">
+<h1><a id="mfc-ranges" name="mfc-ranges">MFC Ranges</a></h1>
+<p>If the <tt class="docutils literal"><span class="pre"><boost/range/mfc.hpp></span></tt> is included before or after <a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> headers,
+the MFC collections and strings become models of Range.
+The table below lists the Traversal Category and <tt class="docutils literal"><span class="pre">range_reference</span></tt> of MFC ranges.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="34%" />
+<col width="21%" />
+<col width="45%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head"><tt class="docutils literal"><span class="pre">Range</span></tt></th>
+<th class="head">Traversal Category</th>
+<th class="head"><tt class="docutils literal"><span class="pre">range_reference<Range>::type</span></tt></th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">CArray<T,A></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">T&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CList<T,A></span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">T&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CMap<K,AK,M,AM></span></tt></td>
+<td>Forward</td>
+<td><tt class="docutils literal"><span class="pre">Range::CPair&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CTypedPtrArray<B,T*></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">T*</span> <span class="pre">const</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CTypedPtrList<B,T*></span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">T*</span> <span class="pre">const</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CTypedPtrMap<B,T*,V*></span></tt></td>
+<td>Forward</td>
+<td><tt class="docutils literal"><span class="pre">std::pair<T*,V*></span> <span class="pre">const</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CByteArray</span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">BYTE&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CDWordArray</span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">DWORD&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CObArray</span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">CObject*</span> <span class="pre">&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CPtrArray</span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">void*</span> <span class="pre">&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CStringArray</span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">CString&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CUIntArray</span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">UINT&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CWordArray</span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">WORD&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CObList</span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">CObject*</span> <span class="pre">&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CPtrList</span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">void*</span> <span class="pre">&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CStringList</span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">CString&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CMapPtrToWord</span></tt></td>
+<td>Forward</td>
+<td><tt class="docutils literal"><span class="pre">std::pair<void*,WORD></span> <span class="pre">const</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CMapPtrToPtr</span></tt></td>
+<td>Forward</td>
+<td><tt class="docutils literal"><span class="pre">std::pair<void*,void*></span> <span class="pre">const</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CMapStringToOb</span></tt></td>
+<td>Forward</td>
+<td><tt class="docutils literal"><span class="pre">std::pair<String,CObject*></span> <span class="pre">const</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CMapStringToString</span></tt></td>
+<td>Forward</td>
+<td><tt class="docutils literal"><span class="pre">Range::CPair&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CMapWordToOb</span></tt></td>
+<td>Forward</td>
+<td><tt class="docutils literal"><span class="pre">std::pair<WORD,CObject*></span> <span class="pre">const</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CMapWordToPtr</span></tt></td>
+<td>Forward</td>
+<td><tt class="docutils literal"><span class="pre">std::pair<WORD,void*></span> <span class="pre">const</span></tt></td>
+</tr>
+</tbody>
+</table>
+<p>Other <a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> metafunctions are defined by the following.
+Let <tt class="docutils literal"><span class="pre">Range</span></tt> be any type listed above and <tt class="docutils literal"><span class="pre">ReF</span></tt> be the same as <tt class="docutils literal"><span class="pre">range_reference<Range>::type</span></tt>.
+<tt class="docutils literal"><span class="pre">range_value<Range>::type</span></tt> is the same as <tt class="docutils literal"><span class="pre">remove_reference<remove_const<Ref>::type>::type</span></tt>,
+<tt class="docutils literal"><span class="pre">range_difference<Range>::type</span></tt> is the same as <tt class="docutils literal"><span class="pre">std::ptrdiff_t</span></tt>, and
+<tt class="docutils literal"><span class="pre">range_pointer<Range>::type</span></tt> is the same as <tt class="docutils literal"><span class="pre">add_pointer<remove_reference<Ref>::type>::type</span></tt>.
+As for <tt class="docutils literal"><span class="pre">const</span> <span class="pre">Range</span></tt>, see <a class="reference" href="#const-ranges">const Ranges</a>.</p>
+</div>
+<div class="section">
+<h1><a id="atl-ranges" name="atl-ranges">ATL Ranges</a></h1>
+<p>If the <tt class="docutils literal"><span class="pre"><boost/range/atl.hpp></span></tt> is included before or after <a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> headers,
+the ATL collections and strings become models of Range.
+The table below lists the Traversal Category and <tt class="docutils literal"><span class="pre">range_reference</span></tt> of ATL ranges.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="34%" />
+<col width="21%" />
+<col width="45%" />
+</colgroup>
+<thead valign="bottom">
+<tr><th class="head"><tt class="docutils literal"><span class="pre">Range</span></tt></th>
+<th class="head">Traversal Category</th>
+<th class="head"><tt class="docutils literal"><span class="pre">range_reference<Range>::type</span></tt></th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr><td><tt class="docutils literal"><span class="pre">CAtlArray<E,ET></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">E&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CAutoPtrArray<E></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">E&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CInterfaceArray<I,pi></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">CComQIPtr<I,pi>&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CAtlList<E,ET></span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">E&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CAutoPtrList<E></span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">E&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CHeapPtrList<E,A></span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">E&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CInterfaceList<I,pi></span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">CComQIPtr<I,pi>&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CAtlMap<K,V,KT,VT></span></tt></td>
+<td>Forward</td>
+<td><tt class="docutils literal"><span class="pre">Range::CPair&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CRBTree<K,V,KT,VT></span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">Range::CPair&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CRBMap<K,V,KT,VT></span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">Range::CPair&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CRBMultiMap<K,V,KT,VT></span></tt></td>
+<td>Bidirectional</td>
+<td><tt class="docutils literal"><span class="pre">Range::CPair&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CSimpleStringT<B,b></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">B&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CStringT<B,ST></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">B&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CFixedStringT<S,n></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">range_reference<S>::type</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CStringT<B,ST></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">B&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CComBSTR</span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">OLECHAR&</span></tt></td>
+</tr>
+<tr><td><tt class="docutils literal"><span class="pre">CSimpleArray<T,TE></span></tt></td>
+<td>Random Access</td>
+<td><tt class="docutils literal"><span class="pre">T&</span></tt></td>
+</tr>
+</tbody>
+</table>
+<p>Other <a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> metafunctions are defined by the following.
+Let <tt class="docutils literal"><span class="pre">Range</span></tt> be any type listed above and <tt class="docutils literal"><span class="pre">ReF</span></tt> be the same as <tt class="docutils literal"><span class="pre">range_reference<Range>::type</span></tt>.
+<tt class="docutils literal"><span class="pre">range_value<Range>::type</span></tt> is the same as <tt class="docutils literal"><span class="pre">remove_reference<Ref>::type</span></tt>,
+<tt class="docutils literal"><span class="pre">range_difference<Range>::type</span></tt> is the same as <tt class="docutils literal"><span class="pre">std::ptrdiff_t</span></tt>, and
+<tt class="docutils literal"><span class="pre">range_pointer<Range>::type</span></tt> is the same as <tt class="docutils literal"><span class="pre">add_pointer<remove_reference<Ref>::type>::type</span></tt>.
+As for <tt class="docutils literal"><span class="pre">const</span> <span class="pre">Range</span></tt>, see <a class="reference" href="#const-ranges">const Ranges</a>.</p>
+</div>
+<div class="section">
+<h1><a id="const-ranges" name="const-ranges">const Ranges</a></h1>
+<p><tt class="docutils literal"><span class="pre">range_reference<const</span> <span class="pre">Range>::type</span></tt> is defined by the following algorithm.
+Let <tt class="docutils literal"><span class="pre">Range</span></tt> be any type listed above and <tt class="docutils literal"><span class="pre">ReF</span></tt> be the same as <tt class="docutils literal"><span class="pre">range_reference<Range>::type</span></tt>.</p>
+<pre class="literal-block">
+if (Range is CObArray || Range is CObList)
+    return CObject const * &
+else if (Range is CPtrArray || Range is CPtrList)
+    return void const * &
+else if (there is a type X such that X& is the same as ReF)
+    return X const &
+else if (there is a type X such that X* const is the same as ReF)
+    return X const * const
+else
+    return ReF
+</pre>
+<p>Other <a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a> metafunctions are defined by the following.
+<tt class="docutils literal"><span class="pre">range_value<const</span> <span class="pre">Range>::type</span></tt> is the same as <tt class="docutils literal"><span class="pre">range_value<Range>::type</span></tt>,
+<tt class="docutils literal"><span class="pre">range_difference<const</span> <span class="pre">Range>::type</span></tt> is the same as <tt class="docutils literal"><span class="pre">std::ptrdiff_t</span></tt>, and
+<tt class="docutils literal"><span class="pre">range_pointer<const</span> <span class="pre">Range>::type</span></tt> is the same as <tt class="docutils literal"><span class="pre">add_pointer<remove_reference<range_reference<const</span> <span class="pre">Range>::type>::type>::type</span></tt>.</p>
+</div>
+<div class="section">
+<h1><a id="references" name="references">References</a></h1>
+<ul class="simple">
+<li><a class="reference" href="http://www.boost.org/libs/range/">Boost.Range</a></li>
+<li><a class="reference" href="http://msdn2.microsoft.com/en-us/library/942860sh.aspx">MFC Collections</a></li>
+<li><a class="reference" href="http://msdn2.microsoft.com/en-US/library/15e672bd.aspx">ATL Collection Classes</a></li>
+</ul>
+</div>
+</div>
+<div class="footer">
+<hr class="footer" />
+<a class="reference" href="mfc_atl.rst">View document source</a>.
+Generated on: 2006-06-04 22:37 UTC.
+Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
+
+</div>
+</body>
+</html>
Added: trunk/libs/range/doc/mfc_atl.rst
==============================================================================
--- (empty file)
+++ trunk/libs/range/doc/mfc_atl.rst	2007-10-23 16:28:52 EDT (Tue, 23 Oct 2007)
@@ -0,0 +1,232 @@
+
+++++++++++++++++++++++++++++++++
+ |Boost| Range MFC/ATL Extension
+++++++++++++++++++++++++++++++++
+
+.. |Boost| image:: http://www.boost.org/libs/ptr_container/doc/boost.png
+
+
+
+:Author:        Shunsuke Sogame
+:Contact:       mb2act_at_[hidden]
+:date:          26th of May 2006
+:copyright:     Shunsuke Sogame 2005-2006. Use, modification and distribution is subject to the Boost Software License, Version 1.0 (see LICENSE_1_0.txt__).
+
+__ http://www.boost.org/LICENSE_1_0.txt
+
+
+
+========
+Overview
+========
+
+Boost.Range MFC/ATL Extension provides `Boost.Range`_ support for MFC/ATL collection and string types.
+
+
+.. parsed-literal::
+
+        CTypedPtrArray<CPtrArray, CList<CString> \*> myArray;
+        ...
+        BOOST_FOREACH (CList<CString> \*theList, myArray)
+        {
+            BOOST_FOREACH (CString& str, \*theList)
+            {
+                boost::to_upper(str);
+                std::sort(boost::begin(str), boost::end(str));
+                ...
+            }
+        }
+
+
+
+* `Requirements`_
+* `MFC Ranges`_
+* `ATL Ranges`_
+* `const Ranges`_
+* `References`_
+
+
+
+============
+Requirements
+============
+
+- `Boost C++ Libraries Version 1.34.0`__ or later (no compilation required)
+- Visual C++ 7.1 or Visual C++ 8.0
+
+__ Boost_
+
+
+
+==========
+MFC Ranges
+==========
+
+If the ``<boost/range/mfc.hpp>`` is included before or after `Boost.Range`_ headers,
+the MFC collections and strings become models of Range.
+The table below lists the Traversal Category and ``range_reference`` of MFC ranges.
+
+
+============================= ================== =======================================
+``Range``                     Traversal Category ``range_reference<Range>::type``
+============================= ================== =======================================
+``CArray<T,A>``               Random Access      ``T&``
+----------------------------- ------------------ ---------------------------------------
+``CList<T,A>``                Bidirectional      ``T&``
+----------------------------- ------------------ ---------------------------------------
+``CMap<K,AK,M,AM>``           Forward            ``Range::CPair&``
+----------------------------- ------------------ ---------------------------------------
+``CTypedPtrArray<B,T*>``      Random Access      ``T* const``
+----------------------------- ------------------ ---------------------------------------
+``CTypedPtrList<B,T*>``       Bidirectional      ``T* const``
+----------------------------- ------------------ ---------------------------------------
+``CTypedPtrMap<B,T*,V*>``     Forward            ``std::pair<T*,V*> const``
+----------------------------- ------------------ ---------------------------------------
+``CByteArray``                Random Access      ``BYTE&``
+----------------------------- ------------------ ---------------------------------------
+``CDWordArray``               Random Access      ``DWORD&``
+----------------------------- ------------------ ---------------------------------------
+``CObArray``                  Random Access      ``CObject* &``
+----------------------------- ------------------ ---------------------------------------
+``CPtrArray``                 Random Access      ``void* &``
+----------------------------- ------------------ ---------------------------------------
+``CStringArray``              Random Access      ``CString&``
+----------------------------- ------------------ ---------------------------------------
+``CUIntArray``                Random Access      ``UINT&``
+----------------------------- ------------------ ---------------------------------------
+``CWordArray``                Random Access      ``WORD&``
+----------------------------- ------------------ ---------------------------------------
+``CObList``                   Bidirectional      ``CObject* &``
+----------------------------- ------------------ ---------------------------------------
+``CPtrList``                  Bidirectional      ``void* &``
+----------------------------- ------------------ ---------------------------------------
+``CStringList``               Bidirectional      ``CString&``
+----------------------------- ------------------ ---------------------------------------
+``CMapPtrToWord``             Forward            ``std::pair<void*,WORD> const``
+----------------------------- ------------------ ---------------------------------------
+``CMapPtrToPtr``              Forward            ``std::pair<void*,void*> const``
+----------------------------- ------------------ ---------------------------------------
+``CMapStringToOb``            Forward            ``std::pair<String,CObject*> const``
+----------------------------- ------------------ ---------------------------------------
+``CMapStringToString``        Forward            ``Range::CPair&``
+----------------------------- ------------------ ---------------------------------------
+``CMapWordToOb``              Forward            ``std::pair<WORD,CObject*> const``
+----------------------------- ------------------ ---------------------------------------
+``CMapWordToPtr``             Forward            ``std::pair<WORD,void*> const``
+============================= ================== =======================================
+
+
+Other `Boost.Range`_ metafunctions are defined by the following.
+Let ``Range`` be any type listed above and ``ReF`` be the same as ``range_reference<Range>::type``.
+``range_value<Range>::type`` is the same as ``remove_reference<remove_const<Ref>::type>::type``,
+``range_difference<Range>::type`` is the same as ``std::ptrdiff_t``, and
+``range_pointer<Range>::type`` is the same as ``add_pointer<remove_reference<Ref>::type>::type``.
+As for ``const Range``, see `const Ranges`_.
+
+
+
+==========
+ATL Ranges
+==========
+
+If the ``<boost/range/atl.hpp>`` is included before or after `Boost.Range`_ headers,
+the ATL collections and strings become models of Range.
+The table below lists the Traversal Category and ``range_reference`` of ATL ranges.
+
+
+============================= ================== =======================================
+``Range``                     Traversal Category ``range_reference<Range>::type``
+============================= ================== =======================================
+``CAtlArray<E,ET>``           Random Access      ``E&``
+----------------------------- ------------------ ---------------------------------------
+``CAutoPtrArray<E>``          Random Access      ``E&``
+----------------------------- ------------------ ---------------------------------------
+``CInterfaceArray<I,pi>``     Random Access      ``CComQIPtr<I,pi>&``
+----------------------------- ------------------ ---------------------------------------
+``CAtlList<E,ET>``            Bidirectional      ``E&``
+----------------------------- ------------------ ---------------------------------------
+``CAutoPtrList<E>``           Bidirectional      ``E&``
+----------------------------- ------------------ ---------------------------------------
+``CHeapPtrList<E,A>``         Bidirectional      ``E&``
+----------------------------- ------------------ ---------------------------------------
+``CInterfaceList<I,pi>``      Bidirectional      ``CComQIPtr<I,pi>&``
+----------------------------- ------------------ ---------------------------------------
+``CAtlMap<K,V,KT,VT>``        Forward            ``Range::CPair&``
+----------------------------- ------------------ ---------------------------------------
+``CRBTree<K,V,KT,VT>``        Bidirectional      ``Range::CPair&``
+----------------------------- ------------------ ---------------------------------------
+``CRBMap<K,V,KT,VT>``         Bidirectional      ``Range::CPair&``
+----------------------------- ------------------ ---------------------------------------
+``CRBMultiMap<K,V,KT,VT>``    Bidirectional      ``Range::CPair&``
+----------------------------- ------------------ ---------------------------------------
+``CSimpleStringT<B,b>``       Random Access      ``B&``
+----------------------------- ------------------ ---------------------------------------
+``CStringT<B,ST>``            Random Access      ``B&``
+----------------------------- ------------------ ---------------------------------------
+``CFixedStringT<S,n>``        Random Access      ``range_reference<S>::type``
+----------------------------- ------------------ ---------------------------------------
+``CStringT<B,ST>``            Random Access      ``B&``
+----------------------------- ------------------ ---------------------------------------
+``CComBSTR``                  Random Access      ``OLECHAR&``
+----------------------------- ------------------ ---------------------------------------
+``CSimpleArray<T,TE>``        Random Access      ``T&``
+============================= ================== =======================================
+
+
+Other `Boost.Range`_ metafunctions are defined by the following.
+Let ``Range`` be any type listed above and ``ReF`` be the same as ``range_reference<Range>::type``.
+``range_value<Range>::type`` is the same as ``remove_reference<Ref>::type``,
+``range_difference<Range>::type`` is the same as ``std::ptrdiff_t``, and
+``range_pointer<Range>::type`` is the same as ``add_pointer<remove_reference<Ref>::type>::type``.
+As for ``const Range``, see `const Ranges`_.
+
+
+
+============
+const Ranges
+============
+
+``range_reference<const Range>::type`` is defined by the following algorithm.
+Let ``Range`` be any type listed above and ``ReF`` be the same as ``range_reference<Range>::type``.
+
+
+.. parsed-literal::
+
+    if (Range is CObArray || Range is CObList)
+        return CObject const \* &
+    else if (Range is CPtrArray || Range is CPtrList)
+        return void const \* &
+    else if (there is a type X such that X& is the same as ReF)
+        return X const &
+    else if (there is a type X such that X* const is the same as ReF)
+        return X const \* const
+    else
+        return ReF
+
+
+Other `Boost.Range`_ metafunctions are defined by the following.
+``range_value<const Range>::type`` is the same as ``range_value<Range>::type``,
+``range_difference<const Range>::type`` is the same as ``std::ptrdiff_t``, and
+``range_pointer<const Range>::type`` is the same as ``add_pointer<remove_reference<range_reference<const Range>::type>::type>::type``.
+
+
+
+==========
+References
+==========
+- `Boost.Range`_
+- `MFC Collections`__
+- `ATL Collection Classes`__
+
+__ http://msdn2.microsoft.com/en-us/library/942860sh.aspx
+__ http://msdn2.microsoft.com/en-US/library/15e672bd.aspx
+
+
+
+.. _Boost C++ Libraries: http://www.boost.org/
+.. _Boost: `Boost C++ Libraries`_
+.. _Boost.Range: http://www.boost.org/libs/range/
+.. _forward: http://www.boost.org/libs/range/doc/range.html#forward_range
+.. _bidirectional: http://www.boost.org/libs/range/doc/range.html#forward_range
+.. _random access: http://www.boost.org/libs/range/doc/range.html#random_access_range
+
Added: trunk/libs/range/test/atl.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/range/test/atl.cpp	2007-10-23 16:28:52 EDT (Tue, 23 Oct 2007)
@@ -0,0 +1,623 @@
+
+
+// Boost.Range ATL Extension
+//
+// Copyright Shunsuke Sogame 2005-2006.
+// Distributed under the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at 
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+// #include <pstade/vodka/drink.hpp>
+
+#include <boost/test/test_tools.hpp>
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define BOOST_LIB_NAME boost_test_exec_monitor
+#include <boost/config/auto_link.hpp>
+
+#define BOOST_RANGE_DETAIL_MICROSOFT_TEST
+#include <boost/range/atl.hpp> // can be placed first
+
+
+#include <map>
+#include <string>
+#include <boost/concept_check.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/distance.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+
+#include <boost/foreach.hpp>
+
+
+#include <atlbase.h> // for ATL3 CSimpleArray/CSimpleValArray
+#if !(_ATL_VER < 0x0700)
+    #include <atlcoll.h>
+    #include <cstringt.h>
+    #include <atlsimpstr.h>
+    #include <atlstr.h>
+#endif
+
+
+namespace brdm = boost::range_detail_microsoft;
+
+
+#if !(_ATL_VER < 0x0700)
+
+
+template< class ArrayT, class SampleRange >
+bool test_init_auto_ptr_array(ArrayT& arr, SampleRange& sample)
+{
+    typedef typename boost::range_iterator<SampleRange>::type iter_t;
+
+    for (iter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) {
+        arr.Add(*it); // moves ownership
+    }
+
+    return boost::distance(arr) == boost::distance(sample);
+}
+
+
+template< class ListT, class SampleRange >
+bool test_init_auto_ptr_list(ListT& lst, SampleRange& sample)
+{
+    typedef typename boost::range_iterator<SampleRange>::type iter_t;
+    typedef typename boost::range_value<SampleRange>::type val_t;
+
+    for (iter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) {
+        lst.AddTail(*it); // moves ownership
+    }
+
+    return boost::distance(lst) == boost::distance(sample);
+}
+
+
+// Workaround:
+// CRBTree provides no easy access function, but yes, it is the range!
+//
+template< class AtlMapT, class KeyT, class MappedT >
+bool test_atl_map_has(AtlMapT& map, const KeyT& k, const MappedT m)
+{
+    typedef typename boost::range_iterator<AtlMapT>::type iter_t;
+
+    for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) {
+        if (it->m_key == k && it->m_value == m)
+            return true;
+    }
+
+    return false;
+}
+
+
+template< class AtlMapT, class MapT >
+bool test_atl_map(AtlMapT& map, const MapT& sample)
+{
+    typedef typename boost::range_iterator<AtlMapT>::type iter_t;
+    typedef typename boost::range_const_iterator<MapT>::type siter_t;
+
+    bool result = true;
+
+    result = result && (boost::distance(map) == boost::distance(sample));
+    if (!result)
+        return false;
+
+    {
+        for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) {
+            result = result && brdm::test_find_key_and_mapped(sample, std::make_pair(it->m_key, it->m_value));
+        }
+    }
+
+    {
+        for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) {
+            result = result && (test_atl_map_has)(map, it->first, it->second);
+        }
+    }
+
+    return result;
+}
+
+
+template< class MapT, class SampleMap >
+bool test_init_atl_multimap(MapT& map, const SampleMap& sample)
+{
+    typedef typename boost::range_const_iterator<SampleMap>::type iter_t;
+
+    for (iter_t it = boost::const_begin(sample), last = boost::const_end(sample); it != last; ++it) {
+        map.Insert(it->first, it->second);
+    }
+
+    return boost::distance(map) == boost::distance(sample);
+}
+
+
+// arrays
+//
+
+template< class Range >
+void test_CAtlArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ATL::CAtlArray<val_t> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, val_t *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, val_t const*>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class ValT, class Range >
+void test_CAutoPtrArray(Range& sample)
+{
+    typedef ValT val_t;
+
+    typedef ATL::CAutoPtrArray<val_t> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, boost::indirect_iterator< ATL::CAutoPtr<val_t> *> >::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, boost::indirect_iterator< ATL::CAutoPtr<val_t> const*> >::value ));
+
+    rng_t rng;
+    BOOST_CHECK( ::test_init_auto_ptr_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class I, class Range >
+void test_CInterfaceArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ATL::CInterfaceArray<I> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, ATL::CComQIPtr<I> * >::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, ATL::CComQIPtr<I> const* >::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+// lists
+//
+
+template< class Range >
+void test_CAtlList(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ATL::CAtlList<val_t> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       val_t> >::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, val_t const> >::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_list(rng, sample) );
+    BOOST_CHECK( brdm::test_bidirectional(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class ValT, class Range >
+void test_CAutoPtrList(Range& sample)
+{
+    typedef ValT val_t;
+
+    typedef ATL::CAutoPtrList<val_t> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, boost::indirect_iterator< brdm::list_iterator<rng_t,       ATL::CAutoPtr<val_t> > > >::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, boost::indirect_iterator< brdm::list_iterator<rng_t const, ATL::CAutoPtr<val_t> const> > >::value ));
+
+    rng_t rng;
+    BOOST_CHECK( ::test_init_auto_ptr_list(rng, sample) );
+    BOOST_CHECK( brdm::test_bidirectional(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class ValT, class Range >
+void test_CHeapPtrList(const Range& sample)
+{
+    typedef ValT val_t;
+
+    typedef ATL::CHeapPtrList<val_t> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, boost::indirect_iterator< brdm::list_iterator<rng_t,       ATL::CHeapPtr<val_t> > > >::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, boost::indirect_iterator< brdm::list_iterator<rng_t const, ATL::CHeapPtr<val_t> const> > >::value ));
+
+    rng_t rng;
+    BOOST_CHECK( ::test_init_auto_ptr_list(rng, sample) );
+    BOOST_CHECK( brdm::test_bidirectional(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class I, class Range >
+void test_CInterfaceList(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ATL::CInterfaceList<I> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       ATL::CComQIPtr<I> > >::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, ATL::CComQIPtr<I> const> >::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_list(rng, sample) );
+    BOOST_CHECK( brdm::test_bidirectional(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+// strings
+//
+
+template< class Range >
+void test_CSimpleStringT(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef typename boost::mpl::if_< boost::is_same<val_t, char>,
+        ATL::CAtlStringA,
+        ATL::CAtlStringW
+    >::type derived_t;
+
+    typedef ATL::CSimpleStringT<val_t> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, typename rng_t::PXSTR>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, typename rng_t::PCXSTR>::value ));
+
+    derived_t drng;
+    rng_t& rng = drng;
+    BOOST_CHECK( brdm::test_init_string(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    // BOOST_CHECK( brdm::test_emptiness(rng) ); no default constructible
+}
+
+
+template< int n, class Range >
+void test_CFixedStringT(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef typename boost::mpl::if_< boost::is_same<val_t, char>,
+        ATL::CAtlStringA,
+        ATL::CAtlStringW
+    >::type base_t;
+
+    typedef ATL::CFixedStringT<base_t, n> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, typename rng_t::PXSTR>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, typename rng_t::PCXSTR>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_string(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class Range >
+void test_CStringT(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef typename boost::mpl::if_< boost::is_same<val_t, char>,
+        ATL::CAtlStringA, // == CStringT<char, X>
+        ATL::CAtlStringW  // == CStringT<wchar_t, X>
+    >::type rng_t;
+
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, typename rng_t::PXSTR>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, typename rng_t::PCXSTR>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_string(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class Range >
+void test_CStaticString(const Range& sample)
+{
+#if !defined(BOOST_RANGE_ATL_NO_TEST_UNDOCUMENTED_RANGE)
+    {
+        typedef ATL::CStaticString<char, 20> rng_t;
+        BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, char const *>::value ));
+        BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, char const *>::value ));
+
+        rng_t rng("hello static string");
+        BOOST_CHECK( *(boost::begin(rng)+4) == 'o' );
+        BOOST_CHECK( *(boost::end(rng)-3) == 'i' );
+    }
+
+    {
+        typedef ATL::CStaticString<wchar_t, 40> rng_t;
+        BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, wchar_t const *>::value ));
+        BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, wchar_t const *>::value ));
+
+        rng_t rng(L"hello static string");
+        BOOST_CHECK( *(boost::begin(rng)+4) == L'o' );
+        BOOST_CHECK( *(boost::end(rng)-3) == L'i' );
+    }
+#endif
+
+    (void)sample; // unused
+}
+
+
+#endif // !(_ATL_VER < 0x0700) 
+
+
+template< class Range >
+void test_CComBSTR(const Range& sample)
+{
+    typedef ATL::CComBSTR rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, OLECHAR *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, OLECHAR const*>::value ));
+
+    rng_t rng(OLESTR("hello CComBSTR range!"));
+    BOOST_CHECK( brdm::test_equals(rng, std::string("hello CComBSTR range!")) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+
+    (void)sample; // unused
+}
+
+
+// simples
+//
+
+template< class Range >
+void test_CSimpleArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ATL::CSimpleArray<val_t> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, val_t *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, val_t const*>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class Range >
+void test_CSimpleMap(const Range& sample)
+{
+#if !defined(BOOST_RANGE_ATL_NO_TEST_UNDOCUMENTED_RANGE)
+
+    typedef ATL::CSimpleMap<int, double> rng_t;
+
+    rng_t rng;
+    rng.Add(3, 3.0);
+    rng.Add(4, 2.0);
+
+    BOOST_CHECK( boost::begin(rng)->get<0>() == 3.0 );
+    BOOST_CHECK( (boost::end(rng)-1)->get<1>() == 2.0 );
+
+#endif
+
+    (void)sample; // unused
+}
+
+
+template< class Range >
+void test_CSimpleValArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ATL::CSimpleArray<val_t> rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, val_t *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, val_t const*>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+// maps
+//
+
+template< class MapT >
+void test_CAtlMap(const MapT& sample)
+{
+    typedef typename MapT::key_type k_t;
+    typedef typename MapT::mapped_type m_t;
+
+    typedef ATL::CAtlMap<k_t, m_t> rng_t;
+
+    rng_t rng;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+    BOOST_CHECK( ::test_atl_map(rng, sample) );
+}
+
+
+template< class MapT >
+void test_CRBTree(const MapT& sample)
+{
+    typedef typename MapT::key_type k_t;
+    typedef typename MapT::mapped_type m_t;
+
+    typedef ATL::CRBMap<k_t, m_t> derived_t;
+    typedef ATL::CRBTree<k_t, m_t> rng_t;
+
+    derived_t drng;
+    rng_t& rng = drng;
+
+    boost::function_requires< boost::BidirectionalRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(drng, sample) );
+    BOOST_CHECK( ::test_atl_map(rng, sample) );
+}
+
+
+template< class MapT >
+void test_CRBMap(const MapT& sample)
+{
+    typedef typename MapT::key_type k_t;
+    typedef typename MapT::mapped_type m_t;
+
+    typedef ATL::CRBMap<k_t, m_t> rng_t;
+
+    rng_t rng;
+    boost::function_requires< boost::BidirectionalRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+    BOOST_CHECK( ::test_atl_map(rng, sample) );
+}
+
+
+template< class MapT >
+void test_CRBMultiMap(const MapT& sample)
+{
+    typedef typename MapT::key_type k_t;
+    typedef typename MapT::mapped_type m_t;
+
+    typedef ATL::CRBMultiMap<k_t, m_t> rng_t;
+
+    rng_t rng;
+    boost::function_requires< boost::BidirectionalRangeConcept<rng_t> >();
+    BOOST_CHECK( ::test_init_atl_multimap(rng, sample) );
+    BOOST_CHECK( ::test_atl_map(rng, sample) );
+}
+
+
+// main test
+//
+
+void test_atl()
+{
+
+    // ordinary ranges
+    //
+    {
+        std::string sample("rebecca judy and mary whiteberry chat monchy");
+#if !(_ATL_VER < 0x0700)
+        ::test_CAtlArray(sample);
+        ::test_CAtlList(sample);
+        ::test_CSimpleStringT(sample);
+        ::test_CFixedStringT<44>(sample);
+        ::test_CStringT(sample);
+        ::test_CStaticString(sample);
+#endif
+        ::test_CComBSTR(sample);
+        ::test_CSimpleArray(sample);
+        ::test_CSimpleMap(sample);
+        ::test_CSimpleValArray(sample);
+    }
+
+
+    {
+        std::wstring sample(L"rebecca judy and mary whiteberry chat monchy");
+#if !(_ATL_VER < 0x0700)
+        ::test_CAtlArray(sample);
+        ::test_CAtlList(sample);
+        ::test_CSimpleStringT(sample);
+        ::test_CFixedStringT<44>(sample);
+        ::test_CStringT(sample);
+        ::test_CStaticString(sample);
+#endif
+        ::test_CComBSTR(sample);
+        ::test_CSimpleArray(sample);
+        ::test_CSimpleMap(sample);
+        ::test_CSimpleValArray(sample);
+    }
+
+    // pointer ranges
+    //
+#if !(_ATL_VER < 0x0700)
+    {
+        typedef ATL::CAutoPtr<int> ptr_t;
+        ptr_t
+            ptr0(new int(3)), ptr1(new int(4)), ptr2(new int(5)), ptr3(new int(4)),
+            ptr4(new int(1)), ptr5(new int(2)), ptr6(new int(4)), ptr7(new int(0));
+
+        ptr_t ptrs[8] = {
+            ptr0, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, ptr7
+        };
+
+        boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+8);
+        ::test_CAutoPtrArray<int>(workaround);
+    }
+
+    {
+        typedef ATL::CAutoPtr<int> ptr_t;
+        ptr_t
+            ptr0(new int(3)), ptr1(new int(4)), ptr2(new int(5)), ptr3(new int(4)),
+            ptr4(new int(1)), ptr5(new int(2)), ptr6(new int(4)), ptr7(new int(0));
+
+        ptr_t ptrs[8] = {
+            ptr0, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, ptr7
+        };
+
+        boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+8);
+        ::test_CAutoPtrList<int>(workaround);
+    }
+
+    {
+        typedef ATL::CHeapPtr<int> ptr_t;
+        ptr_t ptrs[5]; {
+            ptrs[0].AllocateBytes(sizeof(int));
+            ptrs[1].AllocateBytes(sizeof(int));
+            ptrs[2].AllocateBytes(sizeof(int));
+            ptrs[3].AllocateBytes(sizeof(int));
+            ptrs[4].AllocateBytes(sizeof(int));
+        }
+
+        boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+5);
+        ::test_CHeapPtrList<int>(workaround);
+    }
+
+
+    {
+        typedef ATL::CComQIPtr<IDispatch> ptr_t;
+        ptr_t ptrs[8];
+
+        boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+8);
+        ::test_CInterfaceArray<IDispatch>(workaround);
+        ::test_CInterfaceList<IDispatch>(workaround);
+    }
+#endif
+
+    // maps
+    //
+    {
+#if !(_ATL_VER < 0x0700)
+        std::map<int, std::string> sample; {
+            sample[0] = "hello";
+            sample[1] = "range";
+            sample[2] = "atl";
+            sample[3] = "mfc";
+            sample[4] = "collections";
+        }
+
+        ::test_CAtlMap(sample);
+        ::test_CRBTree(sample);
+        ::test_CRBMap(sample);
+        ::test_CRBMultiMap(sample);
+#endif
+    }
+
+
+} // test_atl
+
+
+#include <boost/test/unit_test.hpp>
+using boost::unit_test::test_suite;
+
+
+test_suite *
+init_unit_test_suite(int argc, char* argv[])
+{
+    test_suite *test = BOOST_TEST_SUITE("ATL Range Test Suite");
+    test->add(BOOST_TEST_CASE(&test_atl));
+
+    (void)argc, (void)argv; // unused
+    return test;
+}
Modified: trunk/libs/range/test/mfc.cpp
==============================================================================
--- trunk/libs/range/test/mfc.cpp	(original)
+++ trunk/libs/range/test/mfc.cpp	2007-10-23 16:28:52 EDT (Tue, 23 Oct 2007)
@@ -1,86 +1,745 @@
-// Boost.Range library
+
+
+// Boost.Range MFC Extension
 //
-//  Copyright Thorsten Ottosen 2003-2004. Use, modification and
-//  distribution is subject to the Boost Software License, Version
-//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
-//  http://www.boost.org/LICENSE_1_0.txt)
+// Copyright Shunsuke Sogame 2005-2006.
+// Distributed under the Boost Software License, Version 1.0. 
+// (See accompanying file LICENSE_1_0.txt or copy at 
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#include <afx.h> // must be here
+
+// #include <pstade/vodka/drink.hpp>
+
+#include <boost/test/test_tools.hpp>
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define BOOST_LIB_NAME boost_test_exec_monitor
+#include <boost/config/auto_link.hpp>
+
+#define BOOST_RANGE_DETAIL_MICROSOFT_TEST
+#include <boost/range/mfc.hpp> // can be placed first
+
+
+#include <map>
+#include <boost/concept_check.hpp>
+// #include <boost/foreach.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/end.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/algorithm/string.hpp>
+
+
+#include <afx.h>
+#include <afxcoll.h>
+#include <afxtempl.h>
+
+#if !(_ATL_VER < 0x0700)
+    #include <cstringt.h>
+    #include <atlsimpstr.h>
+    #include <atlstr.h>
+#endif
+
+
+namespace brdm = boost::range_detail_microsoft;
+
+
+// helpers
 //
-// For more information, see http://www.boost.org/libs/range/
+
+template< class MfcMapT, class MapT >
+bool test_mfc_map(MfcMapT& map, const MapT& sample)
+{
+    typedef typename boost::range_iterator<MfcMapT>::type iter_t;
+    typedef typename boost::range_const_iterator<MapT>::type siter_t;
+
+    bool result = true;
+
+    result = result && (boost::distance(map) == boost::distance(sample));
+    if (!result)
+        return false;
+
+    {
+        for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) {
+            result = result && brdm::test_find_key_and_mapped(sample, *it);
+        }
+    }
+
+    {
+        for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) {
+            result = result && (map[it->first] == it->second);
+        }
+    }
+
+    return result;
+}
+
+
+template< class MfcMapT, class MapT >
+bool test_mfc_cpair_map(MfcMapT& map, const MapT& sample)
+{
+    typedef typename boost::range_iterator<MfcMapT>::type iter_t;
+    typedef typename boost::range_const_iterator<MapT>::type siter_t;
+
+    bool result = true;
+
+    result = result && (boost::distance(map) == boost::distance(sample));
+    if (!result)
+        return false;
+
+    {
+        for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) {
+            result = result && brdm::test_find_key_and_mapped(sample, std::make_pair(it->key, it->value));
+        }
+    }
+
+    {
+        for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) {
+            result = result && (map[it->first] == it->second);
+        }
+    }
+
+    return result;
+}
+
+
+// arrays
 //
+template< class Range >
+void test_CByteArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CByteArray rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, BYTE *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, BYTE const*>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class Range >
+void test_CDWordArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CDWordArray rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, DWORD *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, DWORD const*>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class Range >
+void test_CObArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
 
-#define _MSL_USING_NAMESPACE 1
+    typedef ::CObArray rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, brdm::mfc_ptr_array_iterator<rng_t, ::CObject *> >::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, brdm::mfc_ptr_array_iterator<const rng_t, const ::CObject *> >::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class Range >
+void test_CPtrArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CPtrArray rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, brdm::mfc_ptr_array_iterator<rng_t, void *> >::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, brdm::mfc_ptr_array_iterator<const rng_t, const void *> >::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
 
-#include <boost/detail/workaround.hpp>
 
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-#  pragma warn -8091 // supress warning in Boost.Test
-#  pragma warn -8057 // unused argument argc/argv in Boost.Test
+template< class Range >
+void test_CStringArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CStringArray rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, ::CString *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, ::CString const *>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class Range >
+void test_CUIntArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CUIntArray rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, UINT *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, UINT const *>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class Range >
+void test_CWordArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CWordArray rng_t;
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, WORD *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, WORD const *>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+// lists
+//
+
+template< class Range >
+void test_CObList(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CObList rng_t;
+
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       ::CObject *> >::value ));
+#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, ::CObject const *> >::value ));
+#else
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, ::CObject const * const, ::CObject const * const> >::value ));
 #endif
 
-#define BOOST_RANGE_ENABLE_MFC
-#define BOOST_RANGE_ENABLE_MCF_CARRAY
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_list(rng, sample) );
+    BOOST_CHECK( brdm::test_bidirectional(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
 
-/*
-#define WIN32
-#define _WINDOWS
-#define _MBCS
-#define _AFXDLL
-#define _ATL_DLL
-*/
 
-///Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_MBCS" /D "_AFXDLL" /D "_ATL_DLL" /Gm /EHsc /RTC1 
-// /MDd /Zc:wchar_t /Yu"stdafx.h" /Fp"Debug/Foo.pch" /Fo"Debug/" /Fd"Debug/vc70.pdb" /W3 /nologo /c /Wp64 /ZI /TP
+template< class Range >
+void test_CPtrList(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
 
-#include <boost/range.hpp>
-#include <boost/range/detail/mfc/carray.hpp>
-#include <boost/range/detail/mfc/cstring.hpp>
+    typedef ::CPtrList rng_t;
 
-#include <boost/test/test_tools.hpp>
-#include <boost/config.hpp>
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       void *> >::value ));
+#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, void const *> >::value ));
+#else
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, void const * const, void const * const> >::value ));
+#endif
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_list(rng, sample) );
+    BOOST_CHECK( brdm::test_bidirectional(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
 
 
-void check_mfc()
+template< class Range >
+void test_CStringList(const Range& sample)
 {
-    CString s = "hello world";
-    BOOST_CHECK( boost::begin( s ) + boost::size( s ) == boost::end( s ) );
-    BOOST_CHECK( boost::size( s ) == boost::size( "hello world" ) );
-    BOOST_CHECK( !boost::empty( s ) );
-    const CString cs( s );
-    BOOST_CHECK( boost::begin( cs ) + boost::size( cs ) == boost::end( cs ) );
-    BOOST_CHECK( boost::size( cs ) == boost::size( "hello world" ) );
-    BOOST_CHECK( !boost::empty( cs ) );
-    
-    CArray<int,int> a;
-    BOOST_CHECK( boost::empty( a ) );
-    a.Add( 5 );
-    a.Add( 10 );
-    BOOST_CHECK( boost::begin( a ) + boost::size( a ) == boost::end( a ) );
-    BOOST_CHECK( boost::size( a ) == 2 );
-    BOOST_CHECK( !boost::empty( a ) );
-    const CArray<int,int>& ca = a;
-    BOOST_CHECK( boost::begin( ca ) + boost::size( ca ) == boost::end( ca ) );
-    BOOST_CHECK( boost::size( ca ) == 2 );
-    BOOST_CHECK( !boost::empty( ca ) );
-    
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CStringList rng_t;
+
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       ::CString> >::value ));
+#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, ::CString const> >::value ));
+#else
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, ::CString const, ::CString const> >::value ));
+#endif
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_list(rng, sample) );
+    BOOST_CHECK( brdm::test_bidirectional(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
 }
 
 
+// maps
+//
 
-#include <boost/test/unit_test.hpp>
-using boost::unit_test::test_suite;
+template< class MapT >
+void test_CMapPtrToWord(const MapT& sample)
+{
+    typedef ::CMapPtrToWord rng_t;
+
+    rng_t rng;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+    BOOST_CHECK( ::test_mfc_map(rng, sample) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
 
 
-test_suite* init_unit_test_suite( int argc, char* argv[] )
+template< class MapT >
+void test_CMapPtrToPtr(const MapT& sample)
 {
-    test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" );
+    typedef ::CMapPtrToPtr rng_t;
+
+    rng_t rng;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+    BOOST_CHECK( ::test_mfc_map(rng, sample) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
 
-    test->add( BOOST_TEST_CASE( &check_mfc ) );
 
-    return test;
+template< class MapT >
+void test_CMapStringToOb(const MapT& sample)
+{
+    typedef ::CMapStringToOb rng_t;
+
+    rng_t rng;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+    BOOST_CHECK( ::test_mfc_map(rng, sample) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
 }
 
 
+template< class MapT >
+void test_CMapStringToPtr(const MapT& sample)
+{
+    typedef ::CMapStringToPtr rng_t;
 
+    rng_t rng;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+    BOOST_CHECK( ::test_mfc_map(rng, sample) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
 
 
+template< class MapT >
+void test_CMapStringToString(const MapT& sample)
+{
+    typedef ::CMapStringToString rng_t;
 
+    rng_t rng;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+#if !defined(BOOST_RANGE_MFC_NO_CPAIR)
+    BOOST_CHECK( ::test_mfc_cpair_map(rng, sample) );
+#endif
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class MapT >
+void test_CMapWordToOb(const MapT& sample)
+{
+    typedef ::CMapWordToOb rng_t;
+
+    rng_t rng;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+    BOOST_CHECK( ::test_mfc_map(rng, sample) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class MapT >
+void test_CMapWordToPtr(const MapT& sample)
+{
+    typedef ::CMapWordToPtr rng_t;
+
+    rng_t rng;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+    BOOST_CHECK( ::test_mfc_map(rng, sample) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+// templates
+//
+
+template< class Range >
+void test_CArray(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CArray<val_t, const val_t&> rng_t; // An old MFC needs the second template argument.
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, val_t *>::value ));
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, val_t const*>::value ));
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_array(rng, sample) );
+    BOOST_CHECK( brdm::test_random_access(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class Range >
+void test_CList(const Range& sample)
+{
+    typedef typename boost::range_value<Range>::type val_t;
+
+    typedef ::CList<val_t, const val_t&> rng_t;
+
+    BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator<rng_t,       val_t> >::value ));
+#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF)
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, val_t const> >::value ));
+#else
+    BOOST_STATIC_ASSERT(( brdm::test_const_iter  < rng_t, brdm::list_iterator<rng_t const, val_t const, val_t const> >::value ));
+#endif
+
+    rng_t rng;
+    BOOST_CHECK( brdm::test_init_list(rng, sample) );
+    BOOST_CHECK( brdm::test_bidirectional(rng) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+template< class MapT >
+void test_CMap(const MapT& sample)
+{
+    typedef typename MapT::key_type k_t;
+    typedef typename MapT::mapped_type m_t;
+
+    typedef ::CMap<k_t, const k_t&, m_t, const m_t&> rng_t;
+
+    rng_t rng;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+    BOOST_CHECK( brdm::test_init_map(rng, sample) );
+#if !defined(BOOST_RANGE_MFC_NO_CPAIR)
+    BOOST_CHECK( ::test_mfc_cpair_map(rng, sample) );
+#endif
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+void test_CTypedPtrArray()
+{
+    typedef ::CTypedPtrArray< ::CPtrArray, int * > rng_t;
+    boost::function_requires< boost::RandomAccessRangeConcept<rng_t> >();
+
+    rng_t rng;
+    int o1, o2, o3, o4, o5;
+    int *data[] = { &o1, &o2, &o3, &o4, &o5 };
+    BOOST_CHECK( brdm::test_init_array(rng, boost::make_iterator_range(data, data+5)) );
+
+    BOOST_CHECK( *(boost::begin(rng) + 2) == &o3 );
+    BOOST_CHECK( *(boost::end(rng) - 1) == &o5 );        
+
+    // BOOST_CHECK( brdm::test_random_access(rng) ); this range is not mutable
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+void test_CTypedPtrList()
+{
+    typedef ::CTypedPtrList< ::CObList, ::CObList * > rng_t;
+    boost::function_requires< boost::BidirectionalRangeConcept<rng_t> >();
+
+    rng_t rng;
+
+    ::CObList o1, o2, o3, o4, o5;
+    ::CObList *data[] = { &o1, &o2, &o3, &o4, &o5 };
+    BOOST_CHECK( brdm::test_init_list(rng, data) );
+
+    boost::range_iterator<rng_t>::type it = boost::begin(rng);
+    std::advance(it, 1);
+    BOOST_CHECK( *it == &o2 );
+    std::advance(it, 2);
+    BOOST_CHECK( *it == &o4 );
+
+    // BOOST_CHECK( brdm::test_bidirectional(rng) ); this range is not mutable
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+void test_CTypedPtrMap()
+{
+    typedef ::CTypedPtrMap< ::CMapStringToPtr, ::CString, int *> rng_t;
+    boost::function_requires< boost::ForwardRangeConcept<rng_t> >();
+
+    rng_t rng;
+    ::CString o0(_T('a')), o1(_T('c')), o2(_T('f')), o3(_T('q')), o4(_T('g'));
+    int d0, d1, d2, d3, d4;
+    std::map< ::CString, int * > data;
+    data[o0] = &d0, data[o1] = &d1, data[o2] = &d2, data[o3] = &d3, data[o4] = &d4;
+
+    BOOST_CHECK( brdm::test_init_map(rng, data) );
+    BOOST_CHECK( ::test_mfc_map(rng, data) );
+    BOOST_CHECK( brdm::test_emptiness(rng) );
+}
+
+
+// strings
+//
+#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING)
+
+    template< class Range >
+    void test_CString(const Range& sample)
+    {
+        typedef typename boost::range_value<Range>::type val_t;
+
+        typedef ::CString rng_t; // An old MFC needs the second template argument.
+        BOOST_STATIC_ASSERT(( brdm::test_mutable_iter<rng_t, TCHAR *>::value ));
+        BOOST_STATIC_ASSERT(( brdm::test_const_iter  <rng_t, TCHAR const*>::value ));
+
+        rng_t rng;
+        BOOST_CHECK( brdm::test_init_string(rng, sample) );
+        BOOST_CHECK( brdm::test_random_access(rng) );
+        BOOST_CHECK( brdm::test_emptiness(rng) );
+    }
+
+#endif
+
+
+struct CPerson
+{
+    void hello_range() { };
+};
+
+
+void test_mfc()
+{
+#if 0
+    // overview
+    //
+    {
+        CTypedPtrArray<CPtrArray, CList<CString> *> myArray;
+        // ...
+        BOOST_FOREACH (CList<CString> *theList, myArray)
+        {
+            BOOST_FOREACH (CString& str, *theList)
+            {
+                boost::to_upper(str);
+                std::sort(boost::begin(str), boost::end(str));
+                // ...
+            }
+        }
+    }
+#endif
+
+    // arrays
+    //
+    {
+        BYTE data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 };
+
+        ::test_CByteArray(boost::make_iterator_range(data, data+22));
+    }
+
+    {
+        DWORD data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 };
+
+        test_CDWordArray(boost::make_iterator_range(data, data+22));
+    }
+
+    {
+        ::CObArray o1, o2, o3, o4, o5;
+        ::CObject *data[] = { &o1, &o2, &o3, &o4, &o5 };
+
+        ::test_CObArray(boost::make_iterator_range(data, data+5));
+    }
+
+    {
+        ::CPtrArray o1, o2, o3, o4, o5;
+        void *data[] = { &o1, &o2, &o3, &o4, &o5 };
+
+        ::test_CPtrArray(boost::make_iterator_range(data, data+5));
+    }
+
+    {
+        ::CString data[] = {
+            ::CString(_T('0')), ::CString(_T('1')), ::CString(_T('2')), ::CString(_T('3')),
+            ::CString(_T('4')), ::CString(_T('5')), ::CString(_T('6')), ::CString(_T('7'))
+        };
+
+        ::test_CStringArray(boost::make_iterator_range(data, data+8));
+    }
+
+    {
+        ::CUIntArray rng;
+        UINT data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 };
+
+        ::test_CUIntArray(boost::make_iterator_range(data, data+22));
+    }
+
+    {
+        ::CWordArray rng;
+        WORD data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 };
+
+        ::test_CWordArray(boost::make_iterator_range(data, data+22));
+    }
+
+    
+    // lists
+    //
+    {
+        ::CObList rng;
+        ::CObList o1, o2, o3, o4, o5;
+        ::CObject *data[] = { &o1, &o2, &o3, &o4, &o5 };
+
+        ::test_CObList(boost::make_iterator_range(data, data+5));
+    }
+
+    {
+        ::CPtrList rng;
+        ::CPtrList o1, o2, o3, o4, o5;
+        void *data[] = { &o1, &o2, &o3, &o4, &o5 };
+
+        ::test_CPtrList(boost::make_iterator_range(data, data+5));
+    }
+
+    {
+        ::CString data[] = {
+            ::CString(_T('0')), ::CString(_T('1')), ::CString(_T('2')), ::CString(_T('3')),
+            ::CString(_T('4')), ::CString(_T('5')), ::CString(_T('6')), ::CString(_T('7'))
+        };
+
+        ::test_CStringList(boost::make_iterator_range(data, data+8));
+    }
+
+
+    // maps
+    //
+    {
+        std::map<void *, WORD> data;
+        int o0, o1, o2, o3, o4;
+        data[&o0] = 15, data[&o1] = 14, data[&o2] = 3, data[&o3] = 6, data[&o4] = 1;
+
+        ::test_CMapPtrToWord(data);
+    }
+
+    {
+        std::map<void *, void*> data;
+        int o0, o1, o2, o3, o4;
+        data[&o0] = &o3, data[&o1] = &o2, data[&o2] = &o1, data[&o3] = &o0, data[&o4] = &o4;
+
+        ::test_CMapPtrToPtr(data);
+    }
+
+    {
+        std::map< ::CString, CObject * > data;
+        CObArray o0, o1, o2, o3, o4;
+        data[ ::CString('0') ] = &o0, data[ ::CString('1') ] = &o1, data[ ::CString('2') ] = &o2,
+        data[ ::CString('3') ] = &o3, data[ ::CString('4') ] = &o4;
+
+        ::test_CMapStringToOb(data);
+    }
+
+    {
+        std::map< ::CString, void * > data;
+        CObArray o0, o1, o2, o3, o4;
+        data[ ::CString('0') ] = &o0, data[ ::CString('1') ] = &o1, data[ ::CString('2') ] = &o2,
+        data[ ::CString('3') ] = &o3, data[ ::CString('4') ] = &o4;
+
+        ::test_CMapStringToPtr(data);
+    }
+
+    {
+        std::map< ::CString, ::CString > data;
+        CString o0('a'), o1('b'), o2('c'), o3('d'), o4('e');
+        data[ ::CString('0') ] = o0, data[ ::CString('1') ] = o1, data[ ::CString('2') ] = o2,
+        data[ ::CString('3') ] = o3, data[ ::CString('4') ] = o4;
+
+        ::test_CMapStringToString(data);
+    }
+
+    {
+        std::map< WORD, CObject * > data;
+        ::CDWordArray o0, o1, o2, o3, o4;
+        data[21] = &o3, data[52] = &o2, data[12] = &o1, data[76] = &o0, data[54] = &o4;
+
+        ::test_CMapWordToOb(data);
+    }
+
+    {
+        std::map< WORD, void * > data;
+        ::CDWordArray o0, o1, o2, o3, o4;
+        data[21] = &o3, data[52] = &o2, data[12] = &o1, data[76] = &o0, data[54] = &o4;
+
+        ::test_CMapWordToPtr(data);
+    }
+
+    // templates
+    //
+    {
+        std::string data("0987654321qwertyuiop");
+        ::test_CArray(data);
+        ::test_CList(data);
+    }    
+
+    {
+        std::wstring data(L"asdfghjklzxcvbnm");
+        ::test_CArray(data);
+        ::test_CList(data);
+    }    
+
+    {
+        std::map< int, std::string > data;
+        data[0] = "abcde", data[1] = "ajfie", data[2] = "lij", data[3] = "abc", data[4] = "ioiu";
+
+        ::test_CMap(data);
+    }
+
+
+    // typed
+    //
+    {
+        ::test_CTypedPtrArray();
+        ::test_CTypedPtrList();
+        ::test_CTypedPtrMap();
+    }
+
+
+    // strings
+    //
+#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING)
+    {
+        std::string data("123456789 abcdefghijklmn");
+        ::test_CString(data);
+    }
+#endif
+
+
+} // test_mfc
+
+
+#include <boost/test/unit_test.hpp>
+using boost::unit_test::test_suite;
+
+
+test_suite *
+init_unit_test_suite(int argc, char* argv[])
+{
+    test_suite *test = BOOST_TEST_SUITE("MFC Range Test Suite");
+    test->add(BOOST_TEST_CASE(&test_mfc));
+
+    (void)argc, (void)argv; // unused
+    return test;
+}