handled volatile/ref-qualified/noexcept memfun key extraction (#24)

This commit is contained in:
joaquintides 2019-06-09 17:32:46 +02:00
parent 32b7f257c2
commit e49ae2b4c2
7 changed files with 548 additions and 47 deletions

View File

@ -56,7 +56,9 @@ Compiler specifics
<code>"boost/multi_index/mem_fun.hpp"</code> synopsis</a>
<ul>
<li><a href="#const_mem_fun">Class template <code>const_mem_fun</code></a></li>
<li><a href="#cv_mem_fun">Class templates <code>cv_mem_fun</code>, <code>cref_mem_fun</code> and <code>cvref_mem_fun</code></a></li>
<li><a href="#mem_fun">Class template <code>mem_fun</code></a></li>
<li><a href="#volatile_mem_fun">Class templates <code>volatile_mem_fun</code>, <code>ref_mem_fun</code> and <code>vref_mem_fun</code></a></li>
<li><a href="#const_mem_fun_explicit">Class templates <code>const_mem_fun_explicit</code> and <code>mem_fun_explicit</code></a></li>
<li><a href="#boost_multi_index_const_mem_fun">Macros <code>BOOST_MULTI_INDEX_CONST_MEM_FUN</code> and <code>BOOST_MULTI_INDEX_MEM_FUN</code></a></li>
</ul>
@ -141,17 +143,22 @@ for every <code>k1</code> of type <code>const KeyFromValue</code> and
</p>
<p>
Boost.MultiIndex provides six general-purpose key extractors:
Boost.MultiIndex provides twelve general-purpose key extractors:
<ul>
<li><a href="#identity"><code>identity</code></a>,</li>
<li><a href="#member"><code>member</code></a>,</li>
<li><a href="#const_mem_fun"><code>const_mem_fun</code></a>,</li>
<li><a href="#mem_fun"><code>mem_fun</code></a>,</li>
<li><a href="#const_mem_fun"><code>const_mem_fun</code></a>
(and three <a href="#cv_mem_fun">variants</a>),
</li>
<li><a href="#mem_fun"><code>mem_fun</code></a>
(and three <a href="#volatile_mem_fun">variants</a>),
</li>
<li><a href="#global_fun"><code>global_fun</code></a> and</li>
<li><a href="#composite_key"><code>composite_key</code></a>,</li>
</ul>
plus, in C++17 compliant environments, an alias template <a href="#key"><code>key</code></a>
allowing for a very terse specification of the latter five extractors.
allowing for a very terse specification of the previous extractors
(except <code>identity</code>).
</p>
<h3><a name="chained_pointers">Chained pointers</a></h3>
@ -429,9 +436,33 @@ to plain <code>member</code> because it provides a slightly more concise syntax.
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Class</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(</span><span class=identifier>Class</span><span class=special>::*</span><span class=identifier>PtrToMemberFunction</span><span class=special>)()</span><span class=keyword>const</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>const_mem_fun</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>class</span> <span class=identifier>Class</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(</span><span class=identifier>Class</span><span class=special>::*</span><span class=identifier>PtrToMemberFunction</span><span class=special>)()</span><span class=keyword>const</span> <span class=keyword>volatile</span>
<span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>cv_mem_fun</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Class</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(</span><span class=identifier>Class</span><span class=special>::*</span><span class=identifier>PtrToMemberFunction</span><span class=special>)()</span><span class=keyword>const</span><span class=special>&amp;</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>cref_mem_fun</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>class</span> <span class=identifier>Class</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(</span><span class=identifier>Class</span><span class=special>::*</span><span class=identifier>PtrToMemberFunction</span><span class=special>)()</span><span class=keyword>const</span> <span class=keyword>volatile</span><span class=special>&amp;</span>
<span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>cvref_mem_fun</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Class</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(</span><span class=identifier>Class</span><span class=special>::*</span><span class=identifier>PtrToMemberFunction</span><span class=special>)()&gt;</span>
<span class=keyword>struct</span> <span class=identifier>mem_fun</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Class</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(</span><span class=identifier>Class</span><span class=special>::*</span><span class=identifier>PtrToMemberFunction</span><span class=special>)()</span><span class=keyword>volatile</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>volatile_mem_fun</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Class</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(</span><span class=identifier>Class</span><span class=special>::*</span><span class=identifier>PtrToMemberFunction</span><span class=special>)()</span><span class=special>&amp;</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>ref_mem_fun</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>class</span> <span class=identifier>Class</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(</span><span class=identifier>Class</span><span class=special>::*</span><span class=identifier>PtrToMemberFunction</span><span class=special>)()</span><span class=keyword>volatile</span><span class=special>&amp;</span>
<span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>vref_mem_fun</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>class</span> <span class=identifier>Class</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>PtrToMemberFunctionType</span><span class=special>,</span><span class=identifier>PtrToMemberFunctionType</span> <span class=identifier>PtrToMemberFunction</span>
@ -526,6 +557,20 @@ object chained-pointed to by <code>x</code>.
<b>Returns:</b> <code>(x.get().*PtrToMemberFunction)()</code>.
</blockquote>
<h3><a name="cv_mem_fun">Class templates <code>cv_mem_fun</code>, <code>cref_mem_fun</code> and <code>cvref_mem_fun</code></a></h3>
<p>
These <a href="#key_extractors"><code>Key Extractors</code></a> are variants of
<a href="#const_mem_fun"><code>const_mem_fun</code></a> used in the case that the
passed member function is:
<ul>
<li><code>const volatile</code> (<code>cv_mem_fun</code>),</li>
<li><code>const &amp;</code>-qualified (<code>cref_mem_fun</code>),</li>
<li><code>const volatile &amp;</code>-qualified (<code>cvref_mem_fun</code>).</li>
</ul>
Other than this, their interface is exactly the same as that of <code>const_mem_fun</code>.
</p>
<h3><a name="mem_fun">Class template <code>mem_fun</code></a></h3>
<p>
@ -584,6 +629,20 @@ object chained-pointed to by <code>x</code>.
<b>Returns:</b> <code>(x.get().*PtrToMemberFunction)()</code>.
</blockquote>
<h3><a name="volatile_mem_fun">Class templates <code>volatile_mem_fun</code>, <code>ref_mem_fun</code> and <code>vref_mem_fun</code></a></h3>
<p>
These <a href="#key_extractors"><code>Key Extractors</code></a> are variants of
<a href="#mem_fun"><code>mem_fun</code></a> used in the case that the
passed member function is:
<ul>
<li><code>volatile</code> (<code>volatile_mem_fun</code>),</li>
<li><code>&amp;</code>-qualified (<code>ref_mem_fun</code>),</li>
<li><code>volatile &amp;</code>-qualified (<code>vref_mem_fun</code>).</li>
</ul>
Other than this, their interface is exactly the same as that of <code>mem_fun</code>.
</p>
<h3><a name="const_mem_fun_explicit">Class templates <code>const_mem_fun_explicit</code> and <code>mem_fun_explicit</code></a></h3>
<p>
@ -2106,13 +2165,40 @@ resolves to:
if <code>Key</code> is of type <code>Type Class::*</code>,
</li>
<li><a href="#const_mem_fun"><code>const_mem_fun&lt;Class,Type,Key&gt;</code></a>
if <code>Key</code> is of type <code>Type (Class::*)()const</code>,
if <code>Key</code> is of type <code>Type (Class::*)()const</code>
(with ot without <code>noexcept</code>-specification),
</li>
<li><a href="#cv_mem_fun"><code>cv_mem_fun&lt;Class,Type,Key&gt;</code></a>
if <code>Key</code> is of type <code>Type (Class::*)()const volatile</code>
(with ot without <code>noexcept</code>-specification),
</li>
<li><a href="#cv_mem_fun"><code>cref_mem_fun&lt;Class,Type,Key&gt;</code></a>
if <code>Key</code> is of type <code>Type (Class::*)()const&amp;</code>
(with ot without <code>noexcept</code>-specification),
</li>
<li><a href="#cv_mem_fun"><code>cvref_mem_fun&lt;Class,Type,Key&gt;</code></a>
if <code>Key</code> is of type <code>Type (Class::*)()const volatile&amp;</code>
(with ot without <code>noexcept</code>-specification),
</li>
<li><a href="#mem_fun"><code>mem_fun&lt;Class,Type,Key&gt;</code></a>
if <code>Key</code> is of type <code>Type (Class::*)()</code>,
if <code>Key</code> is of type <code>Type (Class::*)()</code>
(with ot without <code>noexcept</code>-specification),
</li>
<li><a href="#volatile_mem_fun"><code>volatile_mem_fun&lt;Class,Type,Key&gt;</code></a>
if <code>Key</code> is of type <code>Type (Class::*)()volatile</code>
(with ot without <code>noexcept</code>-specification),
</li>
<li><a href="#volatile_mem_fun"><code>ref_mem_fun&lt;Class,Type,Key&gt;</code></a>
if <code>Key</code> is of type <code>Type (Class::*)()&amp;</code>
(with ot without <code>noexcept</code>-specification),
</li>
<li><a href="#volatile_mem_fun"><code>vref_mem_fun&lt;Class,Type,Key&gt;</code></a>
if <code>Key</code> is of type <code>Type (Class::*)()volatile&amp;</code>
(with ot without <code>noexcept</code>-specification),
</li>
<li><a href="#global_fun"><code>global_fun&lt;Value,Type,Key&gt;</code></a>
if <code>Key</code> is of type <code>Type (*)(Value)</code>,
if <code>Key</code> is of type <code>Type (*)(Value)</code>
(with ot without <code>noexcept</code>-specification),
</li>
</ul>
and engenders undefined behavior otherwise. When passed two or more arguments,
@ -2150,9 +2236,9 @@ Compiler specifics
<br>
<p>Revised August 22nd 2018</p>
<p>Revised June 9th 2019</p>
<p>&copy; Copyright 2003-2018 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2019 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

View File

@ -30,6 +30,7 @@ Acknowledgements
<h2>Contents</h2>
<ul>
<li><a href="#boost_1_71">Boost 1.71 release</a></li>
<li><a href="#boost_1_70">Boost 1.70 release</a></li>
<li><a href="#boost_1_69">Boost 1.69 release</a></li>
<li><a href="#boost_1_68">Boost 1.68 release</a></li>
@ -60,6 +61,22 @@ Acknowledgements
<li><a href="#boost_1_33">Boost 1.33 release</a></li>
</ul>
<h2><a name="boost_1_71">Boost 1.71 release</a></h2>
<p>
<ul>
<li>Added <a href="tutorial/key_extraction.html#x_mem_fun">variants of
<code>const_mem_fun</code> and <code>mem_fun</code></a> for
differently qualified member functions
(<a href="https://github.com/boostorg/multi_index/issues/24">issue #24</a>).
</li>
<li>Terse <a href="reference/key_extraction.html#key">key</a> specification syntax
now correctly handles <code>noexcept</code>-specified member functions
(<a href="https://github.com/boostorg/multi_index/issues/24">issue #24</a>).
</li>
</ul>
</p>
<h2><a name="boost_1_70">Boost 1.70 release</a></h2>
<p>
@ -618,9 +635,9 @@ Acknowledgements
<br>
<p>Revised December 30th 2018</p>
<p>Revised June 9th 2019</p>
<p>&copy; Copyright 2003-2018 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2019 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

View File

@ -39,8 +39,11 @@ Container creation
<ul>
<li><a href="#identity"><code>identity</code></a></li>
<li><a href="#member"><code>member</code></a></li>
<li><a href="#const_mem_fun"><code>const_mem_fun</code>
and <code>mem_fun</code></a></li>
<li><a href="#const_mem_fun"><code>const_mem_fun</code> and <code>mem_fun</code></a>
<ul>
<li><a href="#x_mem_fun">Variants for other types of member functions</a></li>
</ul>
</li>
<li><a href="#global_fun"><code>global_fun</code></a></li>
</ul>
</li>
@ -246,10 +249,97 @@ of Boost.MultiIndex key extractors</a>.
provides a complete program showing how to use <code>const_mem_fun</code>.
<p>
<h4><a name="x_mem_fun">Variants for other types of member functions</a></h4>
<p>
Consider the following, non-compiling code:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>employee</span>
<span class=special>{</span>
<span class=special>...</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>salary</span><span class=special>()</span><span class=keyword>const</span><span class=special><b>&amp;</b>;</span> <span class=comment>// note the &amp;</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=special>...</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span>
<span class=comment>// compiler error: can't convert &amp;employee::salary to
// std::size_t (employee::*)() const</span>
<span class=identifier><b>const_mem_fun</b></span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>salary</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_set</span><span class=special>;</span>
</pre></blockquote>
<p>
The problem here is that the type of <code>&amp;employee::salary</code>, which is
<a href="https://en.cppreference.com/w/cpp/language/member_functions#const-.2C_volatile-.2C_and_ref-qualified_member_functions">ref-qualified</a>,
does not match exactly what <code>const_mem_fun</code> expects. Fortunatey, Boost.MultiIndex
provides a variant to fit:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=special>...</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span>
<span class=identifier><b>cref_mem_fun</b></span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>salary</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_set</span><span class=special>;</span>
</pre></blockquote>
<p>
This is the list of all available variants of <code>const_mem_fun</code> and
<code>mem_fun</code>:
</p>
<p align="center">
<table cellspacing="0">
<caption><b>Variants of <code>const_mem_fun</code> and <code>mem_fun</code>.</b></caption>
<tr>
<th>&nbsp;Member function example&nbsp;</th>
<th>Suitable extractor</th>
<th>Behaves as</th>
</tr>
<tr>
<td><code>int f()const volatile</code></td>
<td><a href="../reference/key_extraction.html#cv_mem_fun"><code>cv_mem_fun</code></a><code>&lt;int,X,&amp;X::f&gt;</code></td>
<td align="center" rowspan="3">&nbsp;<code>const_mem_fun</code>&nbsp;</td>
</tr>
<tr>
<td><code>int f()const&amp;</code></td>
<td><a href="../reference/key_extraction.html#cv_mem_fun"><code>cref_mem_fun</code></a><code>&lt;int,X,&amp;X::f&gt;</code></td>
</tr>
<tr>
<td><code>int f()const volatile&amp;</code></td>
<td><a href="../reference/key_extraction.html#cv_mem_fun"><code>cvref_mem_fun</code></a><code>&lt;int,X,&amp;X::f&gt;</code></td>
</tr>
<tr>
<td><code>int f()volatile</code></td>
<td><a href="../reference/key_extraction.html#volatile_mem_fun"><code>volatile_mem_fun</code></a><code>&lt;int,X,&amp;X::f&gt;</code></td>
<td align="center" rowspan="3"><code>mem_fun</code></td>
</tr>
<tr>
<td><code>int f()&amp;</code></td>
<td><a href="../reference/key_extraction.html#volatile_mem_fun"><code>ref_mem_fun</code></a><code>&lt;int,X,&amp;X::f&gt;</code></td>
</tr>
<tr>
<td><code>int f()volatile&amp;</code></td>
<td><a href="../reference/key_extraction.html#volatile_mem_fun"><code>vref_mem_fun</code></a><code>&lt;int,X,&amp;X::f&gt;</code></td>
</tr>
</table>
</p>
<h3><a name="global_fun"><code>global_fun</code></a></h3>
<p>
Whereas <code>const_mem_fun</code> and <code>mem_fun</code> are based on a
Whereas <code>const_mem_fun</code> and its variants are based on a
given member function of the base type from where the key is extracted,
<a href="../reference/key_extraction.html#global_fun"><code>global_fun</code></a>
takes a global function (or static member function) accepting the base
@ -638,8 +728,10 @@ which results in the exact same defined type, as
<a href="../reference/key_extraction.html#key"><code>key</code></a> constructs are mere
aliases for the old syntax. <code>key</code> can be used to shorten the specification of
<a href="../reference/key_extraction.html#member"><code>member</code></a>,
<a href="../reference/key_extraction.html#const_mem_fun"><code>const_mem_fun</code></a>,
<a href="../reference/key_extraction.html#mem_fun"><code>mem_fun</code></a>,
<a href="../reference/key_extraction.html#const_mem_fun"><code>const_mem_fun</code></a>
(and <a href="../reference/key_extraction.html#cv_mem_fun">variants</a>),
<a href="../reference/key_extraction.html#mem_fun"><code>mem_fun</code></a>
(and <a href="../reference/key_extraction.html#volatile_mem_fun">variants</a>),
<a href="../reference/key_extraction.html#global_fun"><code>global_fun</code></a>
and, with additional terseness benefits,
<a href="../reference/key_extraction.html#composite_key"><code>composite_key</code></a>:
@ -1034,9 +1126,9 @@ Container creation
<br>
<p>Revised August 18th 2018</p>
<p>Revised June 9th 2019</p>
<p>&copy; Copyright 2003-2018 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2019 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">

View File

@ -1,4 +1,4 @@
/* Copyright 2003-2018 Joaquin M Lopez Munoz.
/* Copyright 2003-2019 Joaquin M Lopez Munoz.
* 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)
@ -47,21 +47,26 @@ struct typed_key_impl<
using type=member<Class,Type,PtrToMember>;
};
template<
typename Class,typename Type,Type (Class::*PtrToMemberFunction)()const
>
struct typed_key_impl<Type (Class::*)()const,PtrToMemberFunction>
{
using value_type=Class;
using type=const_mem_fun<Class,Type,PtrToMemberFunction>;
#define BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(qualifier,extractor) \
template< \
typename Class,typename Type,Type (Class::*PtrToMemberFunction)()qualifier \
> \
struct typed_key_impl<Type (Class::*)()qualifier,PtrToMemberFunction> \
{ \
using value_type=Class; \
using type=extractor<Class,Type,PtrToMemberFunction>; \
};
template<typename Class,typename Type,Type (Class::*PtrToMemberFunction)()>
struct typed_key_impl<Type (Class::*)(),PtrToMemberFunction>
{
using value_type=Class;
using type=mem_fun<Class,Type,PtrToMemberFunction>;
};
BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL( ,mem_fun)
BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const ,const_mem_fun)
BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(volatile ,volatile_mem_fun)
BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const volatile ,cv_mem_fun)
BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(& ,ref_mem_fun)
BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const& ,cref_mem_fun)
BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(volatile& ,vref_mem_fun)
BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL(const volatile& ,cvref_mem_fun)
#undef BOOST_MULTI_INDEX_KEY_TYPED_KEY_IMPL
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct typed_key_impl<Type (*)(Value),PtrToFunction>
@ -70,11 +75,47 @@ struct typed_key_impl<Type (*)(Value),PtrToFunction>
using type=global_fun<Value,Type,PtrToFunction>;
};
template<typename T>
struct remove_noexcept{using type=T;};
#define BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(qualifier) \
template<typename R,typename C,typename... Args> \
struct remove_noexcept<R(C::*)(Args...)qualifier noexcept> \
{using type=R(C::*)(Args...)qualifier;}; \
\
template<typename R,typename C,typename... Args> \
struct remove_noexcept<R(C::*)(Args...,...)qualifier noexcept> \
{using type=R(C::*)(Args...,...)qualifier;};
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT()
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(volatile)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const volatile)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(&)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const&)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(volatile&)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const volatile&)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(&&)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const&&)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(volatile&&)
BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT(const volatile&&)
#undef BOOST_MULTI_INDEX_KEY_REMOVE_MEMFUN_NOEXCEPT
template<typename R,typename... Args>
struct remove_noexcept<R(*)(Args...)noexcept>{using type=R(*)(Args...);};
template<typename R,typename... Args>
struct remove_noexcept<R(*)(Args...,...)noexcept>
{using type=R(*)(Args...,...);};
template<typename T>
using remove_noexcept_t=typename remove_noexcept<T>::type;
template<auto... Keys>
struct key_impl;
template<auto Key>
struct key_impl<Key>:typed_key_impl<decltype(Key),Key>{};
struct key_impl<Key>:typed_key_impl<remove_noexcept_t<decltype(Key)>,Key>{};
template<typename... Ts>
struct least_generic;

View File

@ -1,4 +1,4 @@
/* Copyright 2003-2015 Joaquin M Lopez Munoz.
/* Copyright 2003-2019 Joaquin M Lopez Munoz.
* 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)
@ -30,17 +30,30 @@ namespace multi_index{
/* mem_fun implements a read-only key extractor based on a given non-const
* member function of a class.
* const_mem_fun does the same for const member functions.
* Additionally, mem_fun and const_mem_fun are overloaded to support
* referece_wrappers of T and "chained pointers" to T's. By chained pointer
* to T we mean a type P such that, given a p of Type P
* Also, the following variations are provided:
* const_mem_fun: const member functions
* volatile_mem_fun: volatile member functions
* cv_mem_fun: const volatile member functions
* ref_mem_fun: ref-qualifed member functions (C++11)
* cref_mem_fun: const ref-qualifed member functions (C++11)
* vref_mem_fun: volatile ref-qualifed member functions (C++11)
* cvref_mem_fun: const volatile ref-qualifed member functions (C++11)
*
* All of these classes are overloaded to support boost::referece_wrappers
* of T and "chained pointers" to T's. By chained pointer to T we mean a type
* P such that, given a p of Type P
* *...n...*x is convertible to T&, for some n>=1.
* Examples of chained pointers are raw and smart pointers, iterators and
* arbitrary combinations of these (vg. T** or unique_ptr<T*>.)
*/
template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const>
struct const_mem_fun
namespace detail{
template<
class Class,typename Type,
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction
>
struct const_mem_fun_impl
{
typedef typename remove_reference<Type>::type result_type;
@ -74,8 +87,11 @@ struct const_mem_fun
}
};
template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()>
struct mem_fun
template<
class Class,typename Type,
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction
>
struct mem_fun_impl
{
typedef typename remove_reference<Type>::type result_type;
@ -104,6 +120,62 @@ struct mem_fun
}
};
} /* namespace multi_index::detail */
template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const>
struct const_mem_fun:detail::const_mem_fun_impl<
Class,Type,Type (Class::*)()const,PtrToMemberFunction
>{};
template<
class Class,typename Type,
Type (Class::*PtrToMemberFunction)()const volatile
>
struct cv_mem_fun:detail::const_mem_fun_impl<
Class,Type,Type (Class::*)()const volatile,PtrToMemberFunction
>{};
template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()>
struct mem_fun:
detail::mem_fun_impl<Class,Type,Type (Class::*)(),PtrToMemberFunction>{};
template<
class Class,typename Type,Type (Class::*PtrToMemberFunction)()volatile
>
struct volatile_mem_fun:detail::mem_fun_impl<
Class,Type,Type (Class::*)()volatile,PtrToMemberFunction
>{};
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
template<
class Class,typename Type,Type (Class::*PtrToMemberFunction)()const&
>
struct cref_mem_fun:detail::const_mem_fun_impl<
Class,Type,Type (Class::*)()const&,PtrToMemberFunction
>{};
template<
class Class,typename Type,
Type (Class::*PtrToMemberFunction)()const volatile&
>
struct cvref_mem_fun:detail::const_mem_fun_impl<
Class,Type,Type (Class::*)()const volatile&,PtrToMemberFunction
>{};
template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()&>
struct ref_mem_fun:
detail::mem_fun_impl<Class,Type,Type (Class::*)()&,PtrToMemberFunction>{};
template<
class Class,typename Type,Type (Class::*PtrToMemberFunction)()volatile&
>
struct vref_mem_fun:detail::mem_fun_impl<
Class,Type,Type (Class::*)()volatile&,PtrToMemberFunction
>{};
#endif
/* MSVC++ 6.0 has problems with const member functions as non-type template
* parameters, somehow it takes them as non-const. const_mem_fun_explicit
* workarounds this deficiency by accepting an extra type parameter that
@ -119,7 +191,8 @@ struct mem_fun
template<
class Class,typename Type,
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction
>
struct const_mem_fun_explicit
{
typedef typename remove_reference<Type>::type result_type;
@ -156,7 +229,8 @@ struct const_mem_fun_explicit
template<
class Class,typename Type,
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction>
typename PtrToMemberFunctionType,PtrToMemberFunctionType PtrToMemberFunction
>
struct mem_fun_explicit
{
typedef typename remove_reference<Type>::type result_type;

View File

@ -1,6 +1,6 @@
/* Boost.MultiIndex test for terse key specification syntax.
*
* Copyright 2003-2018 Joaquin M Lopez Munoz.
* Copyright 2003-2019 Joaquin M Lopez Munoz.
* 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)
@ -39,9 +39,24 @@ struct base
const int cx;
int f(){return x;};
int cf()const{return x;};
int vf()volatile{return x;};
int cvf()const volatile{return x;};
int rf()&{return x;};
int crf()const&{return x;};
int vrf()volatile&{return x;};
int cvrf()const volatile&{return x;};
int nef()noexcept{return x;};
int cnef()const noexcept{return x;};
int vnef()volatile noexcept{return x;};
int cvnef()const volatile noexcept{return x;};
int rnef()& noexcept{return x;};
int crnef()const& noexcept{return x;};
int vrnef()volatile& noexcept{return x;};
int cvrnef()const volatile& noexcept{return x;};
};
int gf(const base& b){return b.x;}
int negf(const base& b)noexcept{return b.x;}
struct derived:base
{
@ -67,9 +82,54 @@ void test_key()
BOOST_TEST((std::is_same<
key<&base::cf>,const_mem_fun<base,int,&base::cf>
>::value));
BOOST_TEST((std::is_same<
key<&base::vf>,volatile_mem_fun<base,int,&base::vf>
>::value));
BOOST_TEST((std::is_same<
key<&base::cvf>,cv_mem_fun<base,int,&base::cvf>
>::value));
BOOST_TEST((std::is_same<
key<&base::rf>,ref_mem_fun<base,int,&base::rf>
>::value));
BOOST_TEST((std::is_same<
key<&base::crf>,cref_mem_fun<base,int,&base::crf>
>::value));
BOOST_TEST((std::is_same<
key<&base::vrf>,vref_mem_fun<base,int,&base::vrf>
>::value));
BOOST_TEST((std::is_same<
key<&base::cvrf>,cvref_mem_fun<base,int,&base::cvrf>
>::value));
BOOST_TEST((std::is_same<
key<&base::nef>,mem_fun<base,int,&base::nef>
>::value));
BOOST_TEST((std::is_same<
key<&base::cnef>,const_mem_fun<base,int,&base::cnef>
>::value));
BOOST_TEST((std::is_same<
key<&base::vnef>,volatile_mem_fun<base,int,&base::vnef>
>::value));
BOOST_TEST((std::is_same<
key<&base::cvnef>,cv_mem_fun<base,int,&base::cvnef>
>::value));
BOOST_TEST((std::is_same<
key<&base::rnef>,ref_mem_fun<base,int,&base::rnef>
>::value));
BOOST_TEST((std::is_same<
key<&base::crnef>,cref_mem_fun<base,int,&base::crnef>
>::value));
BOOST_TEST((std::is_same<
key<&base::vrnef>,vref_mem_fun<base,int,&base::vrnef>
>::value));
BOOST_TEST((std::is_same<
key<&base::cvrnef>,cvref_mem_fun<base,int,&base::cvrnef>
>::value));
BOOST_TEST((std::is_same<
key<gf>,global_fun<const base&,int,gf>
>::value));
BOOST_TEST((std::is_same<
key<negf>,global_fun<const base&,int,negf>
>::value));
BOOST_TEST((std::is_same<
key<&base::x,&base::cx,&base::f,&base::cf,gf>,
composite_key<

View File

@ -1,6 +1,6 @@
/* Boost.MultiIndex test for key extractors.
*
* Copyright 2003-2015 Joaquin M Lopez Munoz.
* Copyright 2003-2019 Joaquin M Lopez Munoz.
* 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)
@ -28,6 +28,17 @@ struct test_class
bool bool_mem_fun_const()const{return true;}
bool bool_mem_fun(){return false;}
bool bool_mem_fun_volatile()volatile{return false;}
bool bool_mem_fun_cv()const volatile{return true;}
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
bool bool_mem_fun_cref()const&{return true;}
bool bool_mem_fun_ref()&{return false;}
bool bool_mem_fun_vref()volatile&{return false;}
bool bool_mem_fun_cvref()const volatile&{return true;}
#endif
static bool bool_global_fun(test_class){return true;}
static bool bool_global_fun_const_ref(const test_class&){return false;}
@ -66,9 +77,25 @@ typedef identity<const test_class> cidn;
typedef BOOST_MULTI_INDEX_MEMBER(test_class,int,int_member) key_m;
typedef BOOST_MULTI_INDEX_MEMBER(test_class,const int,int_member) ckey_m;
typedef BOOST_MULTI_INDEX_MEMBER(test_class,const int,int_cmember) key_cm;
typedef BOOST_MULTI_INDEX_MEM_FUN(test_class,bool,bool_mem_fun) key_mf;
typedef BOOST_MULTI_INDEX_CONST_MEM_FUN(
test_class,bool,bool_mem_fun_const) key_cmf;
typedef BOOST_MULTI_INDEX_MEM_FUN(test_class,bool,bool_mem_fun) key_mf;
typedef volatile_mem_fun<
test_class,bool,&test_class::bool_mem_fun_volatile> key_vmf;
typedef cv_mem_fun<test_class,bool,&test_class::bool_mem_fun_cv> key_cvmf;
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
typedef cref_mem_fun<
test_class,bool,&test_class::bool_mem_fun_cref> key_crmf;
typedef ref_mem_fun<test_class,bool,&test_class::bool_mem_fun_ref> key_rmf;
typedef vref_mem_fun<
test_class,bool,&test_class::bool_mem_fun_vref> key_vrmf;
typedef cvref_mem_fun<
test_class,bool,&test_class::bool_mem_fun_cvref> key_cvrmf;
#endif
typedef global_fun<test_class,bool,&test_class::bool_global_fun> key_gf;
typedef global_fun<
const test_class&,bool,
@ -165,6 +192,14 @@ void test_key_extractors()
key_cm k_cm;
key_cmf k_cmf;
key_mf k_mf;
key_vmf k_vmf;
key_cvmf k_cvmf;
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
key_crmf k_crmf;
key_rmf k_rmf;
key_vrmf k_vrmf;
key_cvrmf k_cvrmf;
#endif
key_gf k_gf;
key_gcrf k_gcrf;
key_grf k_grf;
@ -313,43 +348,139 @@ void test_key_extractors()
BOOST_TEST(k_cmf(tr));
BOOST_TEST(k_cmf(ctr));
BOOST_TEST(k_cvmf(tr));
BOOST_TEST(k_cvmf(ctr));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(k_crmf(tr));
BOOST_TEST(k_crmf(ctr));
BOOST_TEST(k_cvrmf(tr));
BOOST_TEST(k_cvrmf(ctr));
#endif
#if !defined(BOOST_NO_SFINAE)
BOOST_TEST(k_cmf(td));
BOOST_TEST(k_cmf(ctdr));
BOOST_TEST(k_cvmf(td));
BOOST_TEST(k_cvmf(ctdr));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(k_crmf(td));
BOOST_TEST(k_crmf(ctdr));
BOOST_TEST(k_cvrmf(td));
BOOST_TEST(k_cvrmf(ctdr));
#endif
#endif
BOOST_TEST(k_cmf(tp));
BOOST_TEST(k_cmf(ctp));
BOOST_TEST(k_cvmf(tp));
BOOST_TEST(k_cvmf(ctp));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(k_crmf(tp));
BOOST_TEST(k_crmf(ctp));
BOOST_TEST(k_cvrmf(tp));
BOOST_TEST(k_cvrmf(ctp));
#endif
#if !defined(BOOST_NO_SFINAE)
BOOST_TEST(k_cmf(tdp));
BOOST_TEST(k_cmf(ctdp));
BOOST_TEST(k_cvmf(tdp));
BOOST_TEST(k_cvmf(ctdp));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(k_crmf(tdp));
BOOST_TEST(k_crmf(ctdp));
BOOST_TEST(k_cvrmf(tdp));
BOOST_TEST(k_cvrmf(ctdp));
#endif
#endif
BOOST_TEST(k_cmf(tpp));
BOOST_TEST(k_cmf(ctpp));
BOOST_TEST(k_cmf(tap));
BOOST_TEST(k_cmf(ctap));
BOOST_TEST(k_cvmf(tpp));
BOOST_TEST(k_cvmf(ctpp));
BOOST_TEST(k_cvmf(tap));
BOOST_TEST(k_cvmf(ctap));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(k_crmf(tpp));
BOOST_TEST(k_crmf(ctpp));
BOOST_TEST(k_crmf(tap));
BOOST_TEST(k_crmf(ctap));
BOOST_TEST(k_cvrmf(tpp));
BOOST_TEST(k_cvrmf(ctpp));
BOOST_TEST(k_cvrmf(tap));
BOOST_TEST(k_cvrmf(ctap));
#endif
BOOST_TEST(k_cmf(tw));
BOOST_TEST(k_cmf(ctw));
BOOST_TEST(k_cvmf(tw));
BOOST_TEST(k_cvmf(ctw));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(k_crmf(tw));
BOOST_TEST(k_crmf(ctw));
BOOST_TEST(k_cvrmf(tw));
BOOST_TEST(k_cvrmf(ctw));
#endif
BOOST_TEST(!k_mf(tr));
BOOST_TEST(!k_vmf(tr));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(!k_rmf(tr));
BOOST_TEST(!k_vrmf(tr));
#endif
#if !defined(BOOST_NO_SFINAE)
BOOST_TEST(!k_mf(td));
BOOST_TEST(!k_vmf(td));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(!k_rmf(td));
BOOST_TEST(!k_vrmf(td));
#endif
#endif
BOOST_TEST(!k_mf(tp));
BOOST_TEST(!k_vmf(tp));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(!k_rmf(tp));
BOOST_TEST(!k_vrmf(tp));
#endif
#if !defined(BOOST_NO_SFINAE)
BOOST_TEST(!k_mf(tdp));
BOOST_TEST(!k_vmf(tdp));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(!k_rmf(tdp));
BOOST_TEST(!k_vrmf(tdp));
#endif
#endif
BOOST_TEST(!k_mf(tpp));
BOOST_TEST(!k_mf(tap));
BOOST_TEST(!k_mf(tw));
BOOST_TEST(!k_vmf(tpp));
BOOST_TEST(!k_vmf(tap));
BOOST_TEST(!k_vmf(tw));
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
BOOST_TEST(!k_rmf(tpp));
BOOST_TEST(!k_rmf(tap));
BOOST_TEST(!k_rmf(tw));
BOOST_TEST(!k_vrmf(tpp));
BOOST_TEST(!k_vrmf(tap));
BOOST_TEST(!k_vrmf(tw));
#endif
BOOST_TEST(k_gf(tr));
BOOST_TEST(k_gf(ctr));