summaryrefslogtreecommitdiff
path: root/libs/variant/doc/reference/concepts.xml
blob: 03534ec2c5eee9fa2e37d2bb50f8df6813d5432f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
  "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
    Copyright 2003, Eric Friedman, Itay Maman.

    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)
-->
<section id="variant.concepts">
  <title>Concepts</title>

  <using-namespace name="boost"/>

  <section id="variant.concepts.bounded-type">
    <title><emphasis>BoundedType</emphasis></title>

    <para>The requirements on a <emphasis role="bold">bounded type</emphasis>
      are as follows:</para>

    <itemizedlist>
      <listitem><conceptname>CopyConstructible</conceptname> or <conceptname>MoveConstructible</conceptname>.</listitem>
      <listitem>Destructor upholds the no-throw exception-safety
        guarantee.</listitem>
      <listitem>Complete at the point of <code>variant</code> template
        instantiation. (See
        <code><classname>boost::recursive_wrapper</classname>&lt;T&gt;</code>
        for a type wrapper that accepts incomplete types to enable recursive
        <code>variant</code> types.)</listitem>
    </itemizedlist>

    <para>Every type specified as a template argument to
      <code><classname>variant</classname></code> must at minimum fulfill the
      above requirements. In addition, certain features of <code>variant</code>
      are available only if its bounded types meet the requirements of these
      following additional concepts:</para>

    <itemizedlist>
      <listitem><conceptname>Assignable</conceptname>:
        <code>variant</code> is itself <emphasis>Assignable</emphasis> if and
        only if every one of its bounded types meets the requirements of the
        concept. (Note that top-level <code>const</code>-qualified types and
        reference types do <emphasis>not</emphasis> meet these
        requirements.)</listitem>
      <listitem><conceptname>MoveAssignable</conceptname>:
        <code>variant</code> is itself <emphasis>MoveAssignable</emphasis> if and
        only if every one of its bounded types meets the requirements of the
        concept. (Note that top-level <code>const</code>-qualified types and
        reference types do <emphasis>not</emphasis> meet these
        requirements.)</listitem>
      <listitem><conceptname>DefaultConstructible</conceptname> [20.1.4]:
        <code>variant</code> is itself
        <conceptname>DefaultConstructible</conceptname> if and only if its first
        bounded type (i.e., <code>T1</code>) meets the requirements of the
        concept.</listitem>
      <listitem><conceptname>EqualityComparable</conceptname>:
        <code>variant</code> is itself <conceptname>EqualityComparable</conceptname>
        if and only if every one of its bounded types meets the requirements
        of the concept.</listitem>
      <listitem><conceptname>LessThanComparable</conceptname>:
        <code>variant</code> is itself <conceptname>LessThanComparable</conceptname>
        if and only if every one of its bounded types meets the requirements
        of the concept.</listitem>
      <listitem><link linkend="variant.concepts.output-streamable"><emphasis>OutputStreamable</emphasis></link>:
        <code>variant</code> is itself <emphasis>OutputStreamable</emphasis>
        if and only if every one of its bounded types meets the requirements
        of the concept.</listitem>
      <listitem><link linkend="variant.concepts.hashable"><emphasis>Hashable</emphasis></link>:
        <code>variant</code> is itself <emphasis>Hashable</emphasis>
        if and only if every one of its bounded types meets the requirements
        of the concept.</listitem>
    </itemizedlist>
  </section>

  <section id="variant.concepts.static-visitor">
    <title><emphasis>StaticVisitor</emphasis></title>

    <para>The requirements on a <emphasis role="bold">static
    visitor</emphasis> of a type <code>T</code> are as follows:</para>

    <itemizedlist>
      <listitem>Must allow invocation as a function by overloading
        <code>operator()</code>, unambiguously accepting any value of type
        <code>T</code>.</listitem>
      <listitem>Must expose inner type <code>result_type</code>. C++14 compatible compilers
        could detect <code>result_type</code> automatically, but will stick to
        <code>result_type</code> if it is defined. (See 
        <code><functionname>boost::visitor_ptr</functionname></code> for a
        solution to using functions as visitors.)</listitem>
      <listitem>If <code>result_type</code> is not <code>void</code>, then
        each operation of the function object must return a value implicitly
        convertible to <code>result_type</code>.</listitem>
    </itemizedlist>

    <section id="variant.concepts.static-visitor.examples">
      <title>Examples</title>

      <para>The following class satisfies the requirements of a static visitor
      of several types (i.e., explicitly: <code>int</code> and
      <code>std::string</code>; or, e.g., implicitly: <code>short</code> and
      <code>const char *</code>; etc.):</para>

<programlisting>class my_visitor
    : public <classname>boost::static_visitor</classname>&lt;int&gt;
{
public:

    int operator()(int i)
    {
        return i * 2;
    }

    int operator()(const std::string&amp; s)
    {
        return s.length();
    }

};</programlisting>

      <para>Another example is the following class, whose function-call
      operator is a member template, allowing it to operate on values of many
      types. Thus, the following class is a visitor of any type that supports
      streaming output (e.g., <code>int</code>, <code>double</code>,
      <code>std::string</code>, etc.):</para>

<programlisting>class printer
    : public <classname>boost::static_visitor</classname>&lt;&gt;
{
    template &lt;typename T&gt;
    void operator()(const T&amp; t)
    {
        std::cout &lt;&lt; t &lt;&lt; std::endl;
    }
};</programlisting>

      <para>C++14 compatible compilers detect <code>result_type</code> automatically:</para>

<programlisting>
    <classname>boost::variant</classname>&lt;int, float&gt; v;
    // ...

    <functionname>boost::apply_visitor</functionname>(
        [](auto val) { return std::to_string(val); },
        v
    );
</programlisting>

    </section>
  </section>

  <section id="variant.concepts.output-streamable">
    <title><emphasis>OutputStreamable</emphasis></title>

    <para>The requirements on an <emphasis role="bold">output
      streamable</emphasis> type <code>T</code> are as follows:</para>

    <itemizedlist>
      <listitem>For any object <code>t</code> of type <code>T</code>,
        <code>std::cout &lt;&lt; t</code> must be a valid
        expression.</listitem>
    </itemizedlist>
  </section>

  <section id="variant.concepts.hashable">
    <title><emphasis>Hashable</emphasis></title>

    <para>The requirements on an <emphasis role="bold">hashable</emphasis> type <code>T</code> are as follows:</para>

    <itemizedlist>
      <listitem>For any object <code>t</code> of type <code>T</code>,
        <code>boost::hash&lt;T&gt;()(t)</code> must be a valid
        expression.</listitem>
    </itemizedlist>
  </section>
  
</section>