585 lines
21 KiB
XML
585 lines
21 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
|
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
|
<library name="Any" dirname="any" xmlns:xi="http://www.w3.org/2001/XInclude"
|
|
id="any" last-revision="$Date$">
|
|
<libraryinfo>
|
|
<author>
|
|
<firstname>Kevlin</firstname>
|
|
<surname>Henney</surname>
|
|
</author>
|
|
|
|
<copyright>
|
|
<year>2001</year>
|
|
<holder>Kevlin Henney</holder>
|
|
</copyright>
|
|
|
|
<copyright>
|
|
<year>2013-2019</year>
|
|
<holder>Antony Polukhin</holder>
|
|
</copyright>
|
|
|
|
<librarypurpose>
|
|
Safe, generic container for single values of different value types
|
|
</librarypurpose>
|
|
<librarycategory name="category:data-structures"/>
|
|
|
|
<legalnotice>
|
|
<para>Distributed under the Boost Software License, Version 1.0.
|
|
(See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
|
|
<ulink
|
|
url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
|
|
</para>
|
|
</legalnotice>
|
|
</libraryinfo>
|
|
|
|
<title>Boost.Any</title>
|
|
|
|
<section>
|
|
<title>Introduction</title>
|
|
|
|
<para>There are times when a generic (in the sense of
|
|
<emphasis>general</emphasis> as opposed to
|
|
<emphasis>template-based programming</emphasis>) type is needed:
|
|
variables that are truly variable, accommodating values of many
|
|
other more specific types rather than C++'s normal strict and
|
|
static types. We can distinguish three basic kinds of generic
|
|
type:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Converting types that can hold one of a number of
|
|
possible value types, e.g. <code>int</code> and
|
|
<code>string</code>, and freely convert between them, for
|
|
instance interpreting <code>5</code> as <code>"5"</code> or
|
|
vice-versa. Such types are common in scripting and other
|
|
interpreted
|
|
languages.
|
|
<code><functionname>boost::lexical_cast</functionname></code>
|
|
supports such conversion functionality.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Discriminated types that contain values of different types but
|
|
do not attempt conversion between them, i.e. <code>5</code> is
|
|
held strictly as an <code>int</code> and is not implicitly
|
|
convertible either to <code>"5"</code> or to
|
|
<code>5.0</code>. Their indifference to interpretation but
|
|
awareness of type effectively makes them safe, generic
|
|
containers of single values, with no scope for surprises from
|
|
ambiguous conversions.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Indiscriminate types that can refer to anything but are
|
|
oblivious to the actual underlying type, entrusting all forms
|
|
of access and interpretation to the programmer. This niche is
|
|
dominated by <code>void *</code>, which offers plenty of scope
|
|
for surprising, undefined behavior.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The <code><classname>boost::any</classname></code> class
|
|
(based on the class of the same name described in <ulink
|
|
url="http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf">"Valued
|
|
Conversions"</ulink> by Kevlin Henney, <emphasis>C++
|
|
Report</emphasis> 12(7), July/August 2000) is a variant value type
|
|
based on the second category. It supports copying of any value
|
|
type and safe checked extraction of that value strictly against
|
|
its type. A similar design, offering more appropriate operators,
|
|
can be used for a generalized function adaptor,
|
|
<code>any_function</code>, a generalized iterator adaptor,
|
|
<code>any_iterator</code>, and other object types that need
|
|
uniform runtime treatment but support only compile-time template
|
|
parameter conformance.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Examples</title>
|
|
|
|
<using-namespace name="boost"/>
|
|
<using-class name="boost::any"/>
|
|
|
|
<para>The following code demonstrates the syntax for using
|
|
implicit conversions to and copying of any objects:</para>
|
|
|
|
<programlisting name="any.example.first">
|
|
#include <list>
|
|
#include <boost/any.hpp>
|
|
|
|
using <functionname>boost::any_cast</functionname>;
|
|
typedef std::list<<classname>boost::any</classname>> many;
|
|
|
|
void append_int(many & values, int value)
|
|
{
|
|
<classname>boost::any</classname> to_append = value;
|
|
values.push_back(to_append);
|
|
}
|
|
|
|
void append_string(many & values, const std::string & value)
|
|
{
|
|
values.push_back(value);
|
|
}
|
|
|
|
void append_char_ptr(many & values, const char * value)
|
|
{
|
|
values.push_back(value);
|
|
}
|
|
|
|
void append_any(many & values, const <classname>boost::any</classname> & value)
|
|
{
|
|
values.push_back(value);
|
|
}
|
|
|
|
void append_nothing(many & values)
|
|
{
|
|
values.push_back(<classname>boost::any</classname>());
|
|
}
|
|
</programlisting>
|
|
|
|
<para>The following predicates follow on from the previous
|
|
definitions and demonstrate the use of queries on any
|
|
objects:</para>
|
|
|
|
<programlisting name="any.example.second">
|
|
bool is_empty(const <classname>boost::any</classname> & operand)
|
|
{
|
|
return operand.<methodname>empty</methodname>();
|
|
}
|
|
|
|
bool is_int(const <classname>boost::any</classname> & operand)
|
|
{
|
|
return operand.<methodname>type</methodname>() == typeid(int);
|
|
}
|
|
|
|
bool is_char_ptr(const <classname>boost::any</classname> & operand)
|
|
{
|
|
try
|
|
{
|
|
<functionname>any_cast</functionname><const char *>(operand);
|
|
return true;
|
|
}
|
|
catch(const <classname>boost::bad_any_cast</classname> &)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool is_string(const <classname>boost::any</classname> & operand)
|
|
{
|
|
return <functionname>any_cast</functionname><std::string>(&operand);
|
|
}
|
|
|
|
void count_all(many & values, std::ostream & out)
|
|
{
|
|
out << "#empty == "
|
|
<< std::count_if(values.begin(), values.end(), is_empty) << std::endl;
|
|
out << "#int == "
|
|
<< std::count_if(values.begin(), values.end(), is_int) << std::endl;
|
|
out << "#const char * == "
|
|
<< std::count_if(values.begin(), values.end(), is_char_ptr) << std::endl;
|
|
out << "#string == "
|
|
<< std::count_if(values.begin(), values.end(), is_string) << std::endl;
|
|
}
|
|
</programlisting>
|
|
|
|
<para>The following type, patterned after the OMG's Property Service, defines name-value pairs for arbitrary value types:</para>
|
|
|
|
<programlisting>
|
|
struct property
|
|
{
|
|
property();
|
|
property(const std::string &, const <classname>boost::any</classname> &);
|
|
|
|
std::string name;
|
|
<classname>boost::any</classname> value;
|
|
};
|
|
|
|
typedef std::list<property> properties;
|
|
</programlisting>
|
|
|
|
<para>The following base class demonstrates one approach to
|
|
runtime polymorphism based callbacks that also require arbitrary
|
|
argument types. The absence of virtual member templates requires
|
|
that different solutions have different trade-offs in terms of
|
|
efficiency, safety, and generality. Using a checked variant type
|
|
offers one approach:</para>
|
|
|
|
<programlisting>
|
|
class consumer
|
|
{
|
|
public:
|
|
virtual void notify(const <classname>any</classname> &) = 0;
|
|
...
|
|
};
|
|
</programlisting>
|
|
</section>
|
|
|
|
<library-reference>
|
|
<section id="any.ValueType">
|
|
<title><emphasis>ValueType</emphasis> requirements</title>
|
|
|
|
<para>Values are strongly informational objects for which
|
|
identity is not significant, i.e. the focus is principally on
|
|
their state content and any behavior organized around
|
|
that. Another distinguishing feature of values is their
|
|
granularity: normally fine-grained objects representing simple
|
|
concepts in the system such as quantities.</para>
|
|
|
|
<para>As the emphasis of a value lies in its state not its
|
|
identity, values can be copied and typically assigned one to
|
|
another, requiring the explicit or implicit definition of a
|
|
public copy constructor and public assignment operator. Values
|
|
typically live within other scopes, i.e. within objects or
|
|
blocks, rather than on the heap. Values are therefore normally
|
|
passed around and manipulated directly as variables or through
|
|
references, but not as pointers that emphasize identity and
|
|
indirection.</para>
|
|
|
|
<para>The specific requirements on value types to be used in an
|
|
<code><classname alt="boost::any">any</classname></code>
|
|
are:</para>
|
|
|
|
<itemizedlist spacing="compact">
|
|
<listitem><simpara>A <emphasis>ValueType</emphasis> is
|
|
<emphasis>CopyConstructible</emphasis> [20.1.3].</simpara>
|
|
</listitem>
|
|
|
|
<listitem><simpara>The destructor for a
|
|
<emphasis>ValueType</emphasis> upholds the no-throw
|
|
exception-safety guarantee.</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<header name="boost/any.hpp">
|
|
<namespace name="boost">
|
|
<class name="bad_any_cast">
|
|
<inherit access="public">
|
|
<classname>std::bad_cast</classname>
|
|
</inherit>
|
|
<purpose>The exception thrown in the event of a failed
|
|
<code><functionname>any_cast</functionname></code> of an
|
|
<code><classname>any</classname></code> value.</purpose>
|
|
|
|
<method name="what" specifiers="virtual" cv="const">
|
|
<type>const char *</type>
|
|
</method>
|
|
</class>
|
|
|
|
<class name="any">
|
|
<purpose>A class whose instances can hold instances of any
|
|
type that satisfies <link
|
|
linkend="any.ValueType">ValueType</link>
|
|
requirements.</purpose>
|
|
|
|
<constructor>
|
|
<postconditions><simpara><code>this-><methodname>empty</methodname>()</code></simpara></postconditions>
|
|
</constructor>
|
|
|
|
<constructor>
|
|
<parameter name="other">
|
|
<paramtype>const <classname>any</classname> &</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara> Copy constructor that copies content of
|
|
<code>other</code> into new instance, so that any content
|
|
is equivalent in both type and value to the content of
|
|
<code>other</code>, or empty if <code>other</code> is
|
|
empty. </simpara></effects>
|
|
|
|
<throws><simpara>May fail with a
|
|
<code><classname>std::bad_alloc</classname></code>
|
|
exception or any exceptions arising from the copy
|
|
constructor of the contained type.</simpara></throws>
|
|
</constructor>
|
|
|
|
<constructor>
|
|
<parameter name="other">
|
|
<paramtype><classname>any</classname> &&</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara> Move constructor that moves content of
|
|
<code>other</code> into new instance and leaves <code>other</code>
|
|
empty. </simpara></effects>
|
|
<precondition>C++11 compatible compiler.</precondition>
|
|
<postconditions><simpara><code>other-><methodname>empty</methodname>()</code></simpara></postconditions>
|
|
<throws><simpara>Nothing.</simpara></throws>
|
|
</constructor>
|
|
|
|
<constructor>
|
|
<template>
|
|
<template-type-parameter name="ValueType"/>
|
|
</template>
|
|
|
|
<parameter name="value">
|
|
<paramtype>const ValueType &</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara>Makes a copy of <code>value</code>, so
|
|
that the initial content of the new instance is equivalent
|
|
in both type and value to
|
|
<code>value</code>.</simpara></effects>
|
|
|
|
<throws><simpara><code><classname>std::bad_alloc</classname></code>
|
|
or any exceptions arising from the copy constructor of the
|
|
contained type.</simpara></throws>
|
|
</constructor>
|
|
|
|
<constructor>
|
|
<template>
|
|
<template-type-parameter name="ValueType"/>
|
|
</template>
|
|
|
|
<parameter name="value">
|
|
<paramtype>ValueType &&</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara>Forwards <code>value</code>, so
|
|
that the initial content of the new instance is equivalent
|
|
in both type and value to
|
|
<code>value</code> before the forward.</simpara></effects>
|
|
|
|
<precondition>C++11 compatible compiler.</precondition>
|
|
<throws><simpara><code><classname>std::bad_alloc</classname></code>
|
|
or any exceptions arising from the copy constructor of the
|
|
contained type.</simpara></throws>
|
|
</constructor>
|
|
|
|
<destructor>
|
|
<effects><simpara>Releases any and all resources used in
|
|
management of instance.</simpara></effects>
|
|
<throws><simpara>Nothing.</simpara></throws>
|
|
</destructor>
|
|
|
|
<copy-assignment>
|
|
<type><classname>any</classname> &</type>
|
|
|
|
<parameter name="rhs">
|
|
<paramtype>const <classname>any</classname> &</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara>Copies content of <code>rhs</code> into
|
|
current instance, discarding previous content, so that the
|
|
new content is equivalent in both type and value to the
|
|
content of <code>rhs</code>, or empty if
|
|
<code>rhs.<methodname>empty</methodname>()</code>.</simpara></effects>
|
|
|
|
<throws><simpara><code><classname>std::bad_alloc</classname></code>
|
|
or any exceptions arising from the copy constructor of the
|
|
contained type. Assignment satisfies the strong guarantee
|
|
of exception safety.</simpara></throws>
|
|
</copy-assignment>
|
|
|
|
<copy-assignment>
|
|
<type><classname>any</classname> &</type>
|
|
|
|
<parameter name="rhs">
|
|
<paramtype><classname>any</classname> &&</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara>Moves content of <code>rhs</code> into
|
|
current instance, discarding previous content, so that the
|
|
new content is equivalent in both type and value to the
|
|
content of <code>rhs</code> before move, or empty if
|
|
<code>rhs.<methodname>empty</methodname>()</code>.</simpara></effects>
|
|
|
|
<precondition>C++11 compatible compiler.</precondition>
|
|
<postconditions><simpara><code>rhs-><methodname>empty</methodname>()</code></simpara></postconditions>
|
|
<throws><simpara>Nothing.</simpara></throws>
|
|
</copy-assignment>
|
|
|
|
<copy-assignment>
|
|
<template>
|
|
<template-type-parameter name="ValueType"/>
|
|
</template>
|
|
|
|
<type><classname>any</classname> &</type>
|
|
|
|
<parameter name="rhs">
|
|
<paramtype>const ValueType &</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara>Makes a copy of <code>rhs</code>,
|
|
discarding previous content, so that the new content of is
|
|
equivalent in both type and value to
|
|
<code>rhs</code>.</simpara></effects>
|
|
|
|
<throws><simpara><code><classname>std::bad_alloc</classname></code>
|
|
or any exceptions arising from the copy constructor of the
|
|
contained type. Assignment satisfies the strong guarantee
|
|
of exception safety.</simpara></throws>
|
|
</copy-assignment>
|
|
|
|
<copy-assignment>
|
|
<template>
|
|
<template-type-parameter name="ValueType"/>
|
|
</template>
|
|
|
|
<type><classname>any</classname> &</type>
|
|
|
|
<parameter name="rhs">
|
|
<paramtype>ValueType &&</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara>Forwards <code>rhs</code>,
|
|
discarding previous content, so that the new content of is
|
|
equivalent in both type and value to
|
|
<code>rhs</code> before forward.</simpara></effects>
|
|
|
|
<precondition>C++11 compatible compiler.</precondition>
|
|
<throws><simpara><code><classname>std::bad_alloc</classname></code>
|
|
or any exceptions arising from the move or copy constructor of the
|
|
contained type. Assignment satisfies the strong guarantee
|
|
of exception safety.</simpara></throws>
|
|
</copy-assignment>
|
|
|
|
<method-group name="modifiers">
|
|
<method name="swap">
|
|
<type><classname>any</classname> &</type>
|
|
|
|
<parameter name="rhs">
|
|
<paramtype><classname>any</classname> &</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara>Exchange of the contents of
|
|
<code>*this</code> and
|
|
<code>rhs</code>.</simpara></effects>
|
|
|
|
<returns><simpara><code>*this</code></simpara></returns>
|
|
|
|
<throws><simpara>Nothing.</simpara></throws>
|
|
</method>
|
|
</method-group>
|
|
|
|
<method-group name="queries">
|
|
<method name="empty" cv="const">
|
|
<type>bool</type>
|
|
|
|
<returns><simpara><code>true</code> if instance is
|
|
empty, otherwise <code>false</code>.</simpara></returns>
|
|
|
|
<throws><simpara>Nothing.</simpara></throws>
|
|
</method>
|
|
|
|
<method name="type" cv="const">
|
|
<type>const <classname>std::type_info</classname> &</type>
|
|
|
|
<returns><simpara>the <code>typeid</code> of the
|
|
contained value if instance is non-empty, otherwise
|
|
<code>typeid(void)</code>.</simpara></returns>
|
|
|
|
<notes><simpara>Useful for querying against types known
|
|
either at compile time or only at
|
|
runtime.</simpara></notes>
|
|
</method>
|
|
</method-group>
|
|
</class>
|
|
|
|
<function name="swap">
|
|
<type>void</type>
|
|
<parameter name="lhs">
|
|
<paramtype><classname>any</classname> &</paramtype>
|
|
</parameter>
|
|
<parameter name="rhs">
|
|
<paramtype><classname>any</classname> &</paramtype>
|
|
</parameter>
|
|
|
|
<effects><simpara>Exchange of the contents of
|
|
<code>lhs</code> and
|
|
<code>rhs</code>.</simpara></effects>
|
|
|
|
<throws><simpara>Nothing.</simpara></throws>
|
|
</function>
|
|
|
|
<overloaded-function name="any_cast">
|
|
<signature>
|
|
<template>
|
|
<template-type-parameter name="T"/>
|
|
</template>
|
|
|
|
<type>T</type>
|
|
|
|
<parameter name="operand">
|
|
<paramtype><classname>any</classname> &</paramtype>
|
|
</parameter>
|
|
</signature>
|
|
|
|
<signature>
|
|
<template>
|
|
<template-type-parameter name="T"/>
|
|
</template>
|
|
|
|
<type>T</type>
|
|
|
|
<parameter name="operand">
|
|
<paramtype><classname>any</classname> &&</paramtype>
|
|
</parameter>
|
|
</signature>
|
|
|
|
<signature>
|
|
<template>
|
|
<template-type-parameter name="T"/>
|
|
</template>
|
|
|
|
<type>T</type>
|
|
|
|
<parameter name="operand">
|
|
<paramtype>const <classname>any</classname> &</paramtype>
|
|
</parameter>
|
|
</signature>
|
|
|
|
<signature>
|
|
<template>
|
|
<template-type-parameter name="ValueType"/>
|
|
</template>
|
|
|
|
<type>const ValueType *</type>
|
|
|
|
<parameter name="operand">
|
|
<paramtype>const <classname>any</classname> *</paramtype>
|
|
</parameter>
|
|
</signature>
|
|
|
|
<signature>
|
|
<template>
|
|
<template-type-parameter name="ValueType"/>
|
|
</template>
|
|
|
|
<type>ValueType *</type>
|
|
|
|
<parameter name="operand">
|
|
<paramtype><classname>any</classname> *</paramtype>
|
|
</parameter>
|
|
</signature>
|
|
|
|
<purpose><simpara>Custom keyword cast for extracting a value
|
|
of a given type from an
|
|
<code><classname>any</classname></code>.</simpara></purpose>
|
|
|
|
<returns><simpara> If passed a pointer, it returns a
|
|
similarly qualified pointer to the value content if
|
|
successful, otherwise null is returned.
|
|
If T is ValueType, it returns a copy of the held value, otherwise, if T is a reference
|
|
to (possibly const qualified) ValueType, it returns a reference to the held
|
|
value.</simpara></returns>
|
|
|
|
<throws><simpara>Overloads taking an
|
|
<code><classname>any</classname></code> pointer do not
|
|
throw; overloads taking an
|
|
<code><classname>any</classname></code> value or reference
|
|
throws <code><classname>bad_any_cast</classname></code> if
|
|
unsuccessful.</simpara></throws>
|
|
|
|
</overloaded-function>
|
|
</namespace>
|
|
</header>
|
|
</library-reference>
|
|
|
|
<section>
|
|
<title>Acknowledgements</title>
|
|
|
|
<para>Doug Gregor ported the documentation to the BoostBook format.</para>
|
|
</section>
|
|
</library>
|