introduced C++17 terse key specification syntax

This commit is contained in:
joaquintides 2018-08-17 13:07:53 +02:00
parent 69488c737b
commit 7cc508376c
10 changed files with 477 additions and 25 deletions

View File

@ -98,6 +98,12 @@ Compiler specifics
<li><a href="#ckey_result_semantics">Semantics of <code>composite_key_result</code></a></li>
</ul>
</li>
<li><a href="#key_synopsis">Header
<code>"boost/multi_index/key.hpp"</code> synopsis</a>
<ul>
<li><a href="#key">Alias template <code>key</code></a></li>
</ul>
</li>
</ul>
<h2><a name="key_extractors">Key Extractors</a></h2>
@ -142,8 +148,10 @@ Boost.MultiIndex provides six general-purpose key extractors:
<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="#global_fun"><code>global_fun</code></a> and</li>
<li><a href="#composite_key"><code>composite_key</code></a>.</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.
</p>
<h3><a name="chained_pointers">Chained pointers</a></h3>
@ -2055,6 +2063,77 @@ Therefore, the equivalence classes induced by <code>x==y</code> are
subsets of those associated to <code>!(x&lt;y)&amp;&amp;!(y&lt;x)</code>.
</p>
<h2>
<a name="key_synopsis">Header
<a href="../../../../boost/multi_index/key.hpp">
<code>"boost/multi_index/key.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>mem_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>global_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>composite_key</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#if</span> <span class=identifier>__cplusplus</span><span class=special>&gt;=</span><span class=number>201703L</span>
<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>auto</span><span class=special>...</span> <span class=identifier>Keys</span><span class=special>&gt;</span>
<span class=keyword>using</span> <span class=identifier>key</span><span class=special>=</span><b>implementation defined</b><span class=special>;</span>
<span class=special>}</span> <span class=comment>/* namespace multi_index */</span>
<span class=special>}</span> <span class=comment>/* namespace boost */</span>
<span class=preprocessor>#endif</span>
</pre></blockquote>
<h3><a name="key">Alias template <code>key</code></a></h3>
<p>
In C++17 compliant environments, <code>key</code> provides a very terse syntax for
the specification of Boost.MultiIndex predefined key extractors. The number of template
arguments passed to <code>key</code> must be greater than zero and not exceed the
maximum number of key extractors accepted by
<a href="#composite_key"><code>composite_key</code></a>. <code>key&lt;Key&gt;</code>
resolves to:
<ul>
<li><a href="#member"><code>member&lt;Class,Type,Key&gt;</code></a>
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>,
</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>,
</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>,
</li>
</ul>
and engenders undefined behavior otherwise. When passed two or more arguments,
<code>key&lt;Key0,...,Keyn&gt;</code> resolves to
<a href="#composite_key"><code>composite_key&lt;Value,KeyFromValue0,...,KeyFromValuen&gt;</code></a>,
with:
<ul>
<li><code>KeyFromValuei</code> = <code>key&lt;Keyi&gt;</code>
for all <code>i = 0,...,n</code>
</li>
<li><code>Value</code> = <code>std::decay_t&lt;Value0&gt;</code> &#8855;
<code>std::decay_t&lt;Value1&gt;</code> &#8855; ··· &#8855;
<code>std::decay_t&lt;Valuen&gt;</code>,
</li>
</ul>
where <code>Valuei</code> corresponds to the associated <code>Class</code> or <code>Value</code>
type of <code>KeyFromValuei</code>, and <code>T</code> &#8855; <code>Q</code>
is the <i>least generic type</i> between <code>T</code> and <code>Q</code>, defined as
<code>T</code> if <code>std::is_convertible_v&lt;const T&amp;,const Q&amp;&gt;</code>,
<code>Q</code> if <code>std::is_convertible_v&lt;const Q&amp;,const T&amp;&gt;</code>,
and undefined otherwise.
</p>
<hr>
<div class="prev_link"><a href="rnd_indices.html"><img src="../prev.gif" alt="random access indices" border="0"><br>
@ -2069,9 +2148,9 @@ Compiler specifics
<br>
<p>Revised November 24th 2015</p>
<p>Revised August 17th 2018</p>
<p>&copy; Copyright 2003-2015 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2018 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_69">Boost 1.69 release</a></li>
<li><a href="#boost_1_68">Boost 1.68 release</a></li>
<li><a href="#boost_1_67">Boost 1.67 release</a></li>
<li><a href="#boost_1_66">Boost 1.66 release</a></li>
@ -58,6 +59,17 @@ Acknowledgements
<li><a href="#boost_1_33">Boost 1.33 release</a></li>
</ul>
<h2><a name="boost_1_69">Boost 1.69 release</a></h2>
<p>
<ul>
<li>Introduced an alternative
<a href="tutorial/key_extraction.html#key">terse key specification syntax</a>
for C++17 compliant environments.
</li>
</ul>
</p>
<h2><a name="boost_1_68">Boost 1.68 release</a></h2>
<p>
@ -588,7 +600,7 @@ Acknowledgements
<br>
<p>Revised April 13th 2018</p>
<p>Revised August 17th 2018</p>
<p>&copy; Copyright 2003-2018 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software

View File

@ -79,60 +79,64 @@ with some of the least common features offered by Boost.MultiIndex.
<td>Constant and non-constant iterators and their reverse variants.</td>
</tr>
<tr>
<td><a href="../test/test_key.cpp"><code>test_key.cpp</code></a></td>
<td>Terse key specification syntax.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_key_extractors.cpp"><code>test_key_extractors.cpp</code></a></td>
<td>Covers all use cases of key extractors shipped with the library.</td>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_list_ops.cpp"><code>test_list_ops.cpp</code></a></td>
<td>List-like operations particular to sequenced and random access indices.</td>
</tr>
<tr>
<tr class="odd_tr">
<td><a href="../test/test_modifiers.cpp"><code>test_modifiers.cpp</code></a></td>
<td>Checks the family of insertion and erasing operations.</td>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_mpl_ops.cpp"><code>test_mpl_ops.cpp</code></a></td>
<td>Metaprogramming manipulations of <code>multi_index_container</code> types.</td>
</tr>
<tr>
<tr class="odd_tr">
<td><a href="../test/test_observers.cpp"><code>test_observers.cpp</code></a></td>
<td>Checks observer member functions of ordered and hashed indices.</td>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_projection.cpp"><code>test_projection.cpp</code></a></td>
<td>Projection of iterators among indices.</td>
</tr>
<tr>
<tr class="odd_tr">
<td><a href="../test/test_range.cpp"><code>test_range.cpp</code></a></td>
<td>Exercises the <code>range</code> facility (ordered indices only).</td>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_rank_ops.cpp"><code>test_rank_ops.cpp</code></a></td>
<td>Specific operations of ranked indices.</td>
</tr>
<tr>
<tr class="odd_tr">
<td><a href="../test/test_rearrange.cpp"><code>test_rearrange.cpp</code></a></td>
<td>Rearrange functions of sequenced and random access indices.</td>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_safe_mode.cpp"><code>test_safe_mode.cpp</code></a></td>
<td>Comprehensive coverage of all conditions checked in safe mode.</td>
</tr>
<tr>
<tr class="odd_tr">
<td><a href="../test/test_serialization1.cpp"><code>test_serialization1.cpp</code></a><br>
<a href="../test/test_serialization2.cpp"><code>test_serialization2.cpp</code></a><br>
<a href="../test/test_serialization3.cpp"><code>test_serialization3.cpp</code></a></td>
<td>Serialization support.</td>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_set_ops.cpp"><code>test_set_ops.cpp</code></a></td>
<td>Set-like operations particular to ordered indices.</td>
</tr>
<tr>
<tr class="odd_tr">
<td><a href="../test/test_special_set_ops.cpp"><code>test_special_set_ops.cpp</code></a></td>
<td>Checks special lookup operations using compatible sorting criteria.</td>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_update.cpp"><code>test_update.cpp</code></a></td>
<td><code>replace</code>, <code>modify</code> and <code>modify_key</code>.</td>
</tr>
@ -153,10 +157,9 @@ Future work
<br>
<p>Revised August 17th 2018</p>
<p>Revised April 19th 2015</p>
<p>&copy; Copyright 2003-2015 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2018 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

@ -50,6 +50,7 @@ Container creation
<li><a href="#composite_keys_hash">Composite keys and hashed indices</a></li>
</ul>
</li>
<li><a href="#key">C++17 terse key specification syntax</a></li>
<li><a href="#advanced_key_extractors">Advanced features of Boost.MultiIndex key
extractors</a></li>
</ul>
@ -387,7 +388,7 @@ The analogous concept in Boost.MultiIndex is modeled by means of
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>phonebook_entry</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=comment>//non-unique as some subscribers might have more than one number</span>
<span class=comment>// non-unique as some subscribers might have more than one number</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span>
<span class=identifier>composite_key</span><span class=special>&lt;</span>
<span class=identifier>phonebook_entry</span><span class=special>,</span>
@ -596,6 +597,84 @@ key depends on all of its elements, it is impossible to calculate it from
partial information.
</p>
<h2><a name="key">C++17 terse key specification syntax</a></h2>
<p>
C++17 introduces the declaration of <code>auto</code> template parameters, which can be
taken advantage of to eliminate some redundancy in the specification of Boost.MultiIndex
predefined key extractors. For instance, instead of the classical:
</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=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</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>string</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span>
<span class=identifier>const_mem_fun</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>name_length</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>
one can now write:
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>key</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</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=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>&gt;&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier><b>key</b></span><span class=special><b>&lt;&amp;</b></span><span class=identifier><b>employee</b></span><span class=special><b>::</b></span><span class=identifier><b>name</b></span><span class=special><b>&gt;</b>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier><b>key</b></span><span class=special><b>&lt;&amp;</b></span><span class=identifier><b>employee</b></span><span class=special><b>::</b></span><span class=identifier><b>name_length</b></span><span class=special><b>&gt;</b>&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>
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#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>:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>phonebook_entry</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=comment>// composite key on family name and given name</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;
</span><span class=identifier><b>key</b></span><span class=special><b>&lt;&amp;</b></span><span class=identifier><b>phonebook_entry</b></span><span class=special><b>::</b></span><span class=identifier><b>family_name</b></span><span class=special><b>,&amp;</b></span><span class=identifier><b>phonebook_entry</b></span><span class=special><b>::</b></span><span class=identifier><b>given_name</b></span><span class=special><b>&gt;</b></span>
<span class=special>&gt;,</span>
<span class=comment>// unique index on phone number</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>key</span><span class=special>&lt;&amp;</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>phone_number</span><span class=special>&gt;&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>phonebook</span><span class=special>;</span>
</pre></blockquote>
In this example, the first usage of <code>key</code> substitutes for the
decidedly more cumbersome:
<blockquote><pre>
<span class=identifier>composite_key</span><span class=special>&lt;</span>
<span class=identifier>phonebook_entry</span><span class=special>,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>family_name</span><span class=special>&gt;,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>given_name</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
Note that we did not even have to specifiy the first <code>phonebook_entry</code>
argument: the internal machinery of <code>key</code> automatically deduces it for
us. Check the <a href="../reference/key_extraction.html#key_synopsis">reference</a>
for technical details.
<h2><a name="advanced_key_extractors">Advanced features of Boost.MultiIndex key
extractors</a></h2>
@ -955,9 +1034,9 @@ Container creation
<br>
<p>Revised March 25th 2015</p>
<p>Revised August 17th 2018</p>
<p>&copy; Copyright 2003-2015 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2018 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

@ -0,0 +1,135 @@
/* Copyright 2003-2018 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_KEY_HPP
#define BOOST_MULTI_INDEX_KEY_HPP
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
#if __cplusplus>=201703L
#include <type_traits>
namespace boost{
namespace multi_index{
/* C++17 terse key specification syntax */
namespace detail{
template<auto... Keys>
struct key_impl
{
static_assert(sizeof...(Keys),"at least one key must be provided");
};
template<typename Class,typename Type,Type Class::*PtrToMember>
struct key_impl<PtrToMember>
{
using value_type=Class;
using type=member<Class,Type,PtrToMember>;
};
template<
typename Class,typename Type,Type (Class::*PtrToMemberFunction)()const
>
struct key_impl<PtrToMemberFunction>
{
using value_type=Class;
using type=const_mem_fun<Class,Type,PtrToMemberFunction>;
};
template<typename Class,typename Type,Type (Class::*PtrToMemberFunction)()>
struct key_impl<PtrToMemberFunction>
{
using value_type=Class;
using type=mem_fun<Class,Type,PtrToMemberFunction>;
};
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct key_impl<PtrToFunction>
{
using value_type=Value;
using type=global_fun<Value,Type,PtrToFunction>;
};
template<typename... Ts>
struct least_generic;
template<typename T0,typename... Ts>
struct least_generic<T0,Ts...>
{
using type=T0;
};
template<typename T0,typename T1,typename... Ts>
struct least_generic<T0,T1,Ts...>
{
static_assert(
std::is_convertible_v<const T0&,const T1&>||
std::is_convertible_v<const T1&,const T0&>,
"one type should be convertible to the other");
using type=typename least_generic<
std::conditional_t<std::is_convertible_v<const T0&,const T1&>,T0,T1>,
Ts...
>::type;
};
template<auto Key0,auto... Keys>
struct key_impl<Key0,Keys...>
{
using value_type=typename least_generic<
std::decay_t<typename key_impl<Key0>::value_type>,
std::decay_t<typename key_impl<Keys>::value_type>...
>::type;
using type=composite_key<
value_type,
typename key_impl<Key0>::type,
typename key_impl<Keys>::type...
>;
};
template<typename=composite_key<void,void>>
struct composite_key_size;
template<typename... Args>
struct composite_key_size<composite_key<Args...>>
{
static constexpr auto value=sizeof...(Args)-1;
};
template<auto... Keys>
struct limited_size_key_impl
{
static_assert(
sizeof...(Keys)<=composite_key_size<>::value,
"specified number of keys must meet the limits of "
"boost::multi_index::composite_key");
using type=typename key_impl<Keys...>::type;
};
} /* namespace multi_index::detail */
template<auto... Keys>
using key=typename detail::limited_size_key_impl<Keys...>::type;
} /* namespace multi_index */
} /* namespace boost */
#endif
#endif

View File

@ -1,6 +1,6 @@
# Boost.MultiIndex tests Jamfile
#
# Copyright 2003-2015 Joaqu匤 M L<>ez Mu<4D>z.
# Copyright 2003-2018 Joaquín M López Muñoz.
# 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)
@ -8,7 +8,9 @@
# See http://www.boost.org/libs/multi_index for library home page.
import os ;
import testing ;
import type ;
import ../../config/checks/config : requires ;
# Windows Vista UAC has an heuristic by which executable files whose name
# contains any of the words "install", "setup", "update", etc. are assumed
@ -35,6 +37,10 @@ test-suite "multi_index" :
[ run test_copy_assignment.cpp test_copy_assignment_main.cpp ]
[ run test_hash_ops.cpp test_hash_ops_main.cpp ]
[ run test_iterators.cpp test_iterators_main.cpp ]
[ run test_key.cpp test_key_main.cpp
: : :
[ requires cxx17_std_apply ] # used as a proxy for C++17 support
]
[ run test_key_extractors.cpp test_key_extractors_main.cpp ]
[ run test_list_ops.cpp test_list_ops_main.cpp ]
[ run test_modifiers.cpp test_modifiers_main.cpp ]

View File

@ -1,6 +1,6 @@
/* Boost.MultiIndex test suite.
*
* Copyright 2003-2015 Joaquin M Lopez Munoz.
* Copyright 2003-2018 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)
@ -17,6 +17,7 @@
#include "test_copy_assignment.hpp"
#include "test_hash_ops.hpp"
#include "test_iterators.hpp"
#include "test_key.hpp"
#include "test_key_extractors.hpp"
#include "test_list_ops.hpp"
#include "test_modifiers.hpp"
@ -42,6 +43,7 @@ int main()
test_copy_assignment();
test_hash_ops();
test_iterators();
test_key();
test_key_extractors();
test_list_ops();
test_modifiers();

107
test/test_key.cpp Normal file
View File

@ -0,0 +1,107 @@
/* Boost.MultiIndex test for terse key specification syntax.
*
* Copyright 2003-2018 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#include "test_key.hpp"
#if __cplusplus<201703L
void test_key()
{
/* trivially passes as key is not available for pre-C++17 compilers */
}
#else
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/lightweight_test.hpp>
#include "pre_multi_index.hpp"
#include <boost/multi_index/key.hpp>
#include <functional>
#include <type_traits>
using namespace boost::multi_index;
namespace {
struct base
{
int x;
const int cx;
int f(){return x;};
int cf()const{return x;};
};
int gf(const base& b){return b.x;}
struct derived:base
{
int y;
};
int gh(derived& d){return d.y;}
int grh(std::reference_wrapper<derived>& d){return d.get().y;}
} /* namespace */
void test_key()
{
BOOST_TEST((std::is_same_v<
key<&base::x>,member<base,int,&base::x>
>));
BOOST_TEST((std::is_same_v<
key<&base::cx>,member<base,const int,&base::cx>
>));
BOOST_TEST((std::is_same_v<
key<&base::f>,mem_fun<base,int,&base::f>
>));
BOOST_TEST((std::is_same_v<
key<&base::cf>,const_mem_fun<base,int,&base::cf>
>));
BOOST_TEST((std::is_same_v<
key<gf>,global_fun<const base&,int,gf>
>));
BOOST_TEST((std::is_same_v<
key<&base::x,&base::cx,&base::f,&base::cf,gf>,
composite_key<
base,
member<base,int,&base::x>,
member<base,const int,&base::cx>,
mem_fun<base,int,&base::f>,
const_mem_fun<base,int,&base::cf>,
global_fun<const base&,int,gf>
>
>));
BOOST_TEST((std::is_same_v<
key<&base::x,&derived::y>,
composite_key<
derived,
member<base,int,&base::x>,
member<derived,int,&derived::y>
>
>));
BOOST_TEST((std::is_same_v<
key<gf,gh>,
composite_key<
derived,
global_fun<const base&,int,gf>,
global_fun<derived&,int,gh>
>
>));
BOOST_TEST((std::is_same_v<
key<gf,gh,grh>,
composite_key<
std::reference_wrapper<derived>,
global_fun<const base&,int,gf>,
global_fun<derived&,int,gh>,
global_fun<std::reference_wrapper<derived>&,int,grh>
>
>));
}
#endif

11
test/test_key.hpp Normal file
View File

@ -0,0 +1,11 @@
/* Boost.MultiIndex test for terse key specification syntax.
*
* Copyright 2003-2018 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
void test_key();

18
test/test_key_main.cpp Normal file
View File

@ -0,0 +1,18 @@
/* Boost.MultiIndex test for terse key specification syntax.
*
* Copyright 2003-2018 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#include <boost/detail/lightweight_test.hpp>
#include "test_key.hpp"
int main()
{
test_key();
return boost::report_errors();
}