525 lines
38 KiB
HTML
525 lines
38 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<title>Tutorial</title>
|
||
<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
|
||
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
|
||
<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
|
||
<link rel="up" href="../boost_pfr.html" title="Chapter 28. Boost.PFR 2.0">
|
||
<link rel="prev" href="short_examples_for_the_impatient.html" title="Short Examples for the Impatient">
|
||
<link rel="next" href="limitations_and_configuration.html" title="Limitations and Configuration">
|
||
</head>
|
||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||
<table cellpadding="2" width="100%"><tr>
|
||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
|
||
<td align="center"><a href="../../../index.html">Home</a></td>
|
||
<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
|
||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||
<td align="center"><a href="../../../more/index.htm">More</a></td>
|
||
</tr></table>
|
||
<hr>
|
||
<div class="spirit-nav">
|
||
<a accesskey="p" href="short_examples_for_the_impatient.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../boost_pfr.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="limitations_and_configuration.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||
<a name="boost_pfr.tutorial"></a><a class="link" href="tutorial.html" title="Tutorial">Tutorial</a>
|
||
</h2></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="tutorial.html#boost_pfr.tutorial.why_tuples_are_bad_and_aggregate">Why
|
||
tuples are bad and aggregates are more preferable?</a></span></dt>
|
||
<dt><span class="section"><a href="tutorial.html#boost_pfr.tutorial.accessing_structure_member_by_in">Accessing
|
||
structure member by index</a></span></dt>
|
||
<dt><span class="section"><a href="tutorial.html#boost_pfr.tutorial.custom_printing_of_aggregates">Custom
|
||
printing of aggregates</a></span></dt>
|
||
<dt><span class="section"><a href="tutorial.html#boost_pfr.tutorial.three_ways_of_getting_operators">Three
|
||
ways of getting operators </a></span></dt>
|
||
<dt><span class="section"><a href="tutorial.html#boost_pfr.tutorial.reflection_of_unions">Reflection of
|
||
unions </a></span></dt>
|
||
</dl></div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="boost_pfr.tutorial.why_tuples_are_bad_and_aggregate"></a><a class="link" href="tutorial.html#boost_pfr.tutorial.why_tuples_are_bad_and_aggregate" title="Why tuples are bad and aggregates are more preferable?">Why
|
||
tuples are bad and aggregates are more preferable?</a>
|
||
</h3></div></div></div>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span></code> and <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span></code>
|
||
are good for generic programming, however they have disadvantages. First
|
||
of all, code that uses them becomes barely readable. Consider two definitions:
|
||
</p>
|
||
<div class="informaltable">
|
||
<a name="boost_pfr.tutorial.why_tuples_are_bad_and_aggregate.tuples_vs_aggregates"></a><table class="table">
|
||
<colgroup>
|
||
<col>
|
||
<col>
|
||
</colgroup>
|
||
<thead><tr>
|
||
<th>
|
||
<p>
|
||
Tuple
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Aggregate
|
||
</p>
|
||
</th>
|
||
</tr></thead>
|
||
<tbody><tr>
|
||
<td>
|
||
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">using</span> <span class="identifier">auth_info_tuple</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">tuple</span><span class="special"><</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">int64_t</span><span class="special">,</span> <span class="comment">// What does this integer represents?</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">int64_t</span><span class="special">,</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">time_t</span>
|
||
<span class="special">>;</span>
|
||
</pre>
|
||
</td>
|
||
<td>
|
||
<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"><span class="keyword">struct</span> <span class="identifier">auth_info_aggregate</span> <span class="special">{</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">int64_t</span> <span class="identifier">user_id</span><span class="special">;</span> <span class="comment">// Oh, now I see!</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">int64_t</span> <span class="identifier">session_id</span><span class="special">;</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">time_t</span> <span class="identifier">valid_till</span><span class="special">;</span>
|
||
<span class="special">};</span>
|
||
</pre>
|
||
</td>
|
||
</tr></tbody>
|
||
</table>
|
||
</div>
|
||
<p>
|
||
Definition via aggregate initializable structure is much more clear. Same
|
||
story with usages: <code class="computeroutput"><span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">get</span><span class="special"><</span><span class="number">1</span><span class="special">>(</span><span class="identifier">value</span><span class="special">);</span></code> vs. <code class="computeroutput"><span class="keyword">return</span>
|
||
<span class="identifier">value</span><span class="special">.</span><span class="identifier">session_id</span><span class="special">;</span></code>.
|
||
</p>
|
||
<p>
|
||
Another advantage of aggregates is a more efficient copy, move construction
|
||
and assignments.
|
||
</p>
|
||
<p>
|
||
Because of the above issues some guidelines recommend to <span class="bold"><strong>use
|
||
aggregates instead of tuples</strong></span>. However aggregates fail when it
|
||
comes to the functional like programming.
|
||
</p>
|
||
<p>
|
||
Boost.PFR library <span class="bold"><strong>provides tuple like methods for aggregate
|
||
initializable structures</strong></span>, making aggregates usable in contexts
|
||
where only tuples were useful.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="boost_pfr.tutorial.accessing_structure_member_by_in"></a><a class="link" href="tutorial.html#boost_pfr.tutorial.accessing_structure_member_by_in" title="Accessing structure member by index">Accessing
|
||
structure member by index</a>
|
||
</h3></div></div></div>
|
||
<p>
|
||
The following example shows how to access structure fields by index using
|
||
<code class="computeroutput"><a class="link" href="../boost/pfr/get.html" title="Function get">boost::pfr::get</a></code>.
|
||
</p>
|
||
<p>
|
||
Let's define some structure:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">pfr</span><span class="special">/</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">struct</span> <span class="identifier">foo</span> <span class="special">{</span> <span class="comment">// defining structure</span>
|
||
<span class="keyword">int</span> <span class="identifier">some_integer</span><span class="special">;</span>
|
||
<span class="keyword">char</span> <span class="identifier">c</span><span class="special">;</span>
|
||
<span class="special">};</span>
|
||
</pre>
|
||
<p>
|
||
We can access fields of that structure by index:
|
||
</p>
|
||
<pre class="programlisting"><span class="identifier">foo</span> <span class="identifier">f</span> <span class="special">{</span><span class="number">777</span><span class="special">,</span> <span class="char">'!'</span><span class="special">};</span>
|
||
<span class="keyword">auto</span><span class="special">&</span> <span class="identifier">r1</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">pfr</span><span class="special">::</span><span class="identifier">get</span><span class="special"><</span><span class="number">0</span><span class="special">>(</span><span class="identifier">f</span><span class="special">);</span> <span class="comment">// accessing field with index 0, returns reference to `foo::some_integer`</span>
|
||
<span class="keyword">auto</span><span class="special">&</span> <span class="identifier">r2</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">pfr</span><span class="special">::</span><span class="identifier">get</span><span class="special"><</span><span class="number">1</span><span class="special">>(</span><span class="identifier">f</span><span class="special">);</span> <span class="comment">// accessing field with index 1, returns reference to `foo::c`</span>
|
||
</pre>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="boost_pfr.tutorial.custom_printing_of_aggregates"></a><a class="link" href="tutorial.html#boost_pfr.tutorial.custom_printing_of_aggregates" title="Custom printing of aggregates">Custom
|
||
printing of aggregates</a>
|
||
</h3></div></div></div>
|
||
<p>
|
||
The following example shows how to write your own io-manipulator for printing:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">pfr</span><span class="special">/</span><span class="identifier">ops</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">ostream</span><span class="special">></span>
|
||
|
||
<span class="keyword">namespace</span> <span class="identifier">my_ns</span> <span class="special">{</span>
|
||
|
||
<span class="comment">/// Usage:</span>
|
||
<span class="comment">/// struct foo {std::uint8_t a, b;};</span>
|
||
<span class="comment">/// ...</span>
|
||
<span class="comment">/// std::cout << my_ns::my_io(foo{42, 22});</span>
|
||
<span class="comment">///</span>
|
||
<span class="comment">/// Output: 42, 22</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="keyword">auto</span> <span class="identifier">my_io</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">value</span><span class="special">);</span>
|
||
|
||
<span class="keyword">namespace</span> <span class="identifier">detail</span> <span class="special">{</span>
|
||
<span class="comment">// Helpers to print individual values</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="keyword">void</span> <span class="identifier">print_each</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&</span> <span class="identifier">out</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">v</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">out</span> <span class="special"><<</span> <span class="identifier">v</span><span class="special">;</span> <span class="special">}</span>
|
||
<span class="keyword">void</span> <span class="identifier">print_each</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&</span> <span class="identifier">out</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">uint8_t</span> <span class="identifier">v</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">out</span> <span class="special"><<</span> <span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">unsigned</span><span class="special">>(</span><span class="identifier">v</span><span class="special">);</span> <span class="special">}</span>
|
||
<span class="keyword">void</span> <span class="identifier">print_each</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&</span> <span class="identifier">out</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span> <span class="identifier">v</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">out</span> <span class="special"><<</span> <span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">v</span><span class="special">);</span> <span class="special">}</span>
|
||
|
||
<span class="comment">// Structure to keep a reference to value, that will be ostreamed lower</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="keyword">struct</span> <span class="identifier">io_reference</span> <span class="special">{</span>
|
||
<span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">value</span><span class="special">;</span>
|
||
<span class="special">};</span>
|
||
|
||
<span class="comment">// Output each field of io_reference::value</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&</span> <span class="keyword">operator</span><span class="special"><<(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&</span> <span class="identifier">out</span><span class="special">,</span> <span class="identifier">io_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>&&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
|
||
<span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">sep</span> <span class="special">=</span> <span class="string">""</span><span class="special">;</span>
|
||
|
||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">pfr</span><span class="special">::</span><span class="identifier">for_each_field</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span><span class="special">,</span> <span class="special">[&](</span><span class="keyword">const</span> <span class="keyword">auto</span><span class="special">&</span> <span class="identifier">v</span><span class="special">)</span> <span class="special">{</span>
|
||
<span class="identifier">out</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exchange</span><span class="special">(</span><span class="identifier">sep</span><span class="special">,</span> <span class="string">", "</span><span class="special">);</span>
|
||
<span class="identifier">detail</span><span class="special">::</span><span class="identifier">print_each</span><span class="special">(</span><span class="identifier">out</span><span class="special">,</span> <span class="identifier">v</span><span class="special">);</span>
|
||
<span class="special">});</span>
|
||
<span class="keyword">return</span> <span class="identifier">out</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="comment">// Definition:</span>
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="keyword">auto</span> <span class="identifier">my_io</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">value</span><span class="special">)</span> <span class="special">{</span>
|
||
<span class="keyword">return</span> <span class="identifier">detail</span><span class="special">::</span><span class="identifier">io_reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>{</span><span class="identifier">value</span><span class="special">};</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="special">}</span> <span class="comment">// namespace my_ns</span>
|
||
</pre>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="boost_pfr.tutorial.three_ways_of_getting_operators"></a><a class="link" href="tutorial.html#boost_pfr.tutorial.three_ways_of_getting_operators" title="Three ways of getting operators">Three
|
||
ways of getting operators </a>
|
||
</h3></div></div></div>
|
||
<p>
|
||
There are three ways to start using Boost.PFR hashing, comparison and streaming
|
||
for type <code class="computeroutput"><span class="identifier">T</span></code> in your code.
|
||
Each method has its own drawbacks and suits own cases.
|
||
</p>
|
||
<div class="table">
|
||
<a name="boost_pfr.tutorial.three_ways_of_getting_operators.ops_comp"></a><p class="title"><b>Table 28.1. Different approaches for operators</b></p>
|
||
<div class="table-contents"><table class="table" summary="Different approaches for operators">
|
||
<colgroup>
|
||
<col>
|
||
<col>
|
||
<col>
|
||
<col>
|
||
<col>
|
||
<col>
|
||
<col>
|
||
</colgroup>
|
||
<thead><tr>
|
||
<th>
|
||
<p>
|
||
Approach
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
When to use
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Operators could be found by ADL
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Works for local types
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Usable locally, without affecting code from other scopes
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Ignores implicit conversion operators
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Respects user defined operators
|
||
</p>
|
||
</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../reference_section.html#header.boost.pfr.ops_hpp" title="Header <boost/pfr/ops.hpp>">boost/pfr/ops.hpp: eq, ne,
|
||
gt, lt, le, ge</a></code>
|
||
</p>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../reference_section.html#header.boost.pfr.io_hpp" title="Header <boost/pfr/io.hpp>">boost/pfr/io.hpp: io</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
Use when you need to compare values by provided for them operators
|
||
or via field-by-field comparison.
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
no
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
yes
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
yes
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
no
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
yes
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../BOOST_PFR_FUNCTIONS_FOR.html" title="Macro BOOST_PFR_FUNCTIONS_FOR">BOOST_PFR_FUNCTIONS_FOR(T)</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
Use near the type definition to define the whole set of operators
|
||
for your type.
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
yes
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
no
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
no
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
yes for T
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
no (compile time error)
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../reference_section.html#header.boost.pfr.ops_fields_hpp" title="Header <boost/pfr/ops_fields.hpp>">boost/pfr/ops_fields.hpp:
|
||
eq_fields, ne_fields, gt_fields, lt_fields, le_fields, ge_fields</a></code>
|
||
</p>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../reference_section.html#header.boost.pfr.io_hpp" title="Header <boost/pfr/io.hpp>">boost/pfr/io_fields.hpp: io_fields</a></code>
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
Use to implement the required set of operators for your type.
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
no
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
yes
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
yes
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
yes
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
yes
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table></div>
|
||
</div>
|
||
<br class="table-break"><p>
|
||
More detailed description follows:
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>1. <code class="computeroutput"><span class="identifier">eq</span><span class="special">,</span> <span class="identifier">ne</span><span class="special">,</span>
|
||
<span class="identifier">gt</span><span class="special">,</span> <span class="identifier">lt</span><span class="special">,</span> <span class="identifier">le</span><span class="special">,</span> <span class="identifier">ge</span><span class="special">,</span>
|
||
<span class="identifier">io</span></code> approach</strong></span>
|
||
</p>
|
||
<p>
|
||
This method is good if you're writing generic algorithms and need to use
|
||
operators from Boost.PFR only if there are no operators defined for the type:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">pfr</span><span class="special">/</span><span class="identifier">ops</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||
<span class="keyword">struct</span> <span class="identifier">uniform_comparator_less</span> <span class="special">{</span>
|
||
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">lhs</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">rhs</span><span class="special">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="special">{</span>
|
||
<span class="comment">// If T has operator< or conversion operator then it is used.</span>
|
||
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">pfr</span><span class="special">::</span><span class="identifier">lt</span><span class="special">(</span><span class="identifier">lhs</span><span class="special">,</span> <span class="identifier">rhs</span><span class="special">);</span>
|
||
<span class="special">}</span>
|
||
<span class="special">};</span>
|
||
</pre>
|
||
<p>
|
||
This methods effects are local to the function. It works even for local types,
|
||
like structures defined in functions.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>2. BOOST_PFR_FUNCTIONS_FOR(T) approach</strong></span>
|
||
</p>
|
||
<p>
|
||
This method is good if you're writing a structure and wish to define operators
|
||
for that structure.
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">pfr</span><span class="special">/</span><span class="identifier">functions_for</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">struct</span> <span class="identifier">pair_like</span> <span class="special">{</span>
|
||
<span class="keyword">int</span> <span class="identifier">first</span><span class="special">;</span>
|
||
<span class="keyword">short</span> <span class="identifier">second</span><span class="special">;</span>
|
||
<span class="special">};</span>
|
||
|
||
<span class="identifier">BOOST_PFR_FUNCTIONS_FOR</span><span class="special">(</span><span class="identifier">pair_like</span><span class="special">)</span> <span class="comment">// Defines operators</span>
|
||
|
||
<span class="comment">// ...</span>
|
||
|
||
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">pair_like</span><span class="special">{</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">}</span> <span class="special"><</span> <span class="identifier">pair_like</span><span class="special">{</span><span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">});</span>
|
||
</pre>
|
||
<p>
|
||
Argument Dependant Lookup works well. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">less</span></code>
|
||
will find the operators for <code class="computeroutput"><span class="keyword">struct</span>
|
||
<span class="identifier">pair_like</span></code>. <code class="computeroutput"><a class="link" href="../BOOST_PFR_FUNCTIONS_FOR.html" title="Macro BOOST_PFR_FUNCTIONS_FOR">BOOST_PFR_FUNCTIONS_FOR(T)</a></code>
|
||
can not be used for local types. It does not respect conversion operators
|
||
of <code class="computeroutput"><span class="identifier">T</span></code>, so for example the
|
||
following code will output different values:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">pfr</span><span class="special">/</span><span class="identifier">functions_for</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">struct</span> <span class="identifier">empty</span> <span class="special">{</span>
|
||
<span class="keyword">operator</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="string">"empty{}"</span><span class="special">;</span> <span class="special">}</span>
|
||
<span class="special">};</span>
|
||
<span class="comment">// Uncomment to get different output:</span>
|
||
<span class="comment">// BOOST_PFR_FUNCTIONS_FOR(empty)</span>
|
||
|
||
<span class="comment">// ...</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">empty</span><span class="special">{};</span> <span class="comment">// Outputs `empty{}` if BOOST_PFR_FUNCTIONS_FOR(empty) is commented out, '{}' otherwise.</span>
|
||
</pre>
|
||
<p>
|
||
<span class="bold"><strong>3. <code class="computeroutput"><span class="identifier">eq_fields</span><span class="special">,</span> <span class="identifier">ne_fields</span><span class="special">,</span> <span class="identifier">gt_fields</span><span class="special">,</span> <span class="identifier">lt_fields</span><span class="special">,</span> <span class="identifier">le_fields</span><span class="special">,</span> <span class="identifier">ge_fields</span><span class="special">,</span> <span class="identifier">io_fields</span></code>
|
||
approach</strong></span>
|
||
</p>
|
||
<p>
|
||
This method is good if you're willing to provide only some operators for
|
||
your type:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">pfr</span><span class="special">/</span><span class="identifier">io_fields</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">struct</span> <span class="identifier">pair_like</span> <span class="special">{</span>
|
||
<span class="keyword">int</span> <span class="identifier">first</span><span class="special">;</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">second</span><span class="special">;</span>
|
||
<span class="special">};</span>
|
||
|
||
<span class="keyword">inline</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&</span> <span class="keyword">operator</span><span class="special"><<(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&</span> <span class="identifier">os</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">pair_like</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
|
||
<span class="keyword">return</span> <span class="identifier">os</span> <span class="special"><<</span> <span class="identifier">bost</span><span class="special">::</span><span class="identifier">pfr</span><span class="special">::</span><span class="identifier">io_fields</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
All the <code class="computeroutput"><span class="special">*</span><span class="identifier">_fields</span></code>
|
||
functions do ignore user defined operators and work only with fields of a
|
||
type. This makes them perfect for defining you own operators.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="boost_pfr.tutorial.reflection_of_unions"></a><a class="link" href="tutorial.html#boost_pfr.tutorial.reflection_of_unions" title="Reflection of unions">Reflection of
|
||
unions </a>
|
||
</h3></div></div></div>
|
||
<p>
|
||
You could use tuple-like representation if a type contains union. But be
|
||
sure that operations for union are manually defined:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">pfr</span><span class="special">/</span><span class="identifier">ops</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">union</span> <span class="identifier">test_union</span> <span class="special">{</span>
|
||
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span>
|
||
<span class="keyword">float</span> <span class="identifier">f</span><span class="special">;</span>
|
||
<span class="special">};</span>
|
||
|
||
<span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="identifier">test_union</span> <span class="identifier">l</span><span class="special">,</span> <span class="identifier">test_union</span> <span class="identifier">r</span><span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span> <span class="comment">// Compile time error without this operator</span>
|
||
|
||
<span class="keyword">bool</span> <span class="identifier">some_function</span><span class="special">(</span><span class="identifier">test_union</span> <span class="identifier">f1</span><span class="special">,</span> <span class="identifier">test_union</span> <span class="identifier">f2</span><span class="special">)</span> <span class="special">{</span>
|
||
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">pfr</span><span class="special">::</span><span class="identifier">eq</span><span class="special">(</span><span class="identifier">f1</span><span class="special">,</span> <span class="identifier">f2</span><span class="special">);</span> <span class="comment">// OK</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
Reflection of unions is disabled in the Boost.PFR library for safety reasons.
|
||
Alas, there's no way to find out <span class="bold"><strong>active</strong></span>
|
||
member of a union and accessing an inactive member is an Undefined Behavior.
|
||
For example, library could always return the first member, but ostreaming
|
||
<code class="computeroutput"><span class="identifier">u</span></code> in <code class="computeroutput"><span class="keyword">union</span>
|
||
<span class="special">{</span><span class="keyword">char</span><span class="special">*</span> <span class="identifier">c</span><span class="special">;</span>
|
||
<span class="keyword">long</span> <span class="keyword">long</span>
|
||
<span class="identifier">ll</span><span class="special">;</span> <span class="special">}</span> <span class="identifier">u</span><span class="special">;</span>
|
||
<span class="identifier">u</span><span class="special">.</span><span class="identifier">ll</span><span class="special">=</span> <span class="number">1</span><span class="special">;</span></code> will crash your program with an invalid
|
||
pointer dereference.
|
||
</p>
|
||
<p>
|
||
Any attempt to reflect unions leads to a compile time error. In many cases
|
||
a static assert is triggered that outputs the following message:
|
||
</p>
|
||
<pre class="programlisting"><span class="identifier">error</span><span class="special">:</span> <span class="keyword">static_assert</span> <span class="identifier">failed</span> <span class="string">"====================> Boost.PFR: For safety reasons it is forbidden
|
||
to reflect unions. See `Reflection of unions` section in the docs for more info."</span>
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||
<td align="left"></td>
|
||
<td align="right"><div class="copyright-footer">Copyright © 2016-2021 Antony Polukhin<p>
|
||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||
</p>
|
||
</div></td>
|
||
</tr></table>
|
||
<hr>
|
||
<div class="spirit-nav">
|
||
<a accesskey="p" href="short_examples_for_the_impatient.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../boost_pfr.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="limitations_and_configuration.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
|
||
</div>
|
||
</body>
|
||
</html>
|