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><T></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><int>
{
public:
int operator()(int i)
{
return i * 2;
}
int operator()(const std::string& 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><>
{
template <typename T>
void operator()(const T& t)
{
std::cout << t << std::endl;
}
};</programlisting>
<para>C++14 compatible compilers detect <code>result_type</code> automatically:</para>
<programlisting>
<classname>boost::variant</classname><int, float> 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 << 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<T>()(t)</code> must be a valid
expression.</listitem>
</itemizedlist>
</section>
</section>
|