Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84282 - in branches/release: boost/variant libs/variant/doc/reference libs/variant/doc/tutorial libs/variant/test
From: antoshkka_at_[hidden]
Date: 2013-05-14 14:19:40


Author: apolukhin
Date: 2013-05-14 14:19:39 EDT (Tue, 14 May 2013)
New Revision: 84282
URL: http://svn.boost.org/trac/boost/changeset/84282

Log:
Merge Boost.Variant from trunk
* documentation, tests and implementation of multivisitors (fixes #8459)
Added:
   branches/release/boost/variant/multivisitors.hpp (contents, props changed)
   branches/release/libs/variant/doc/reference/multivisitor.xml (contents, props changed)
   branches/release/libs/variant/test/variant_multivisit_test.cpp (contents, props changed)
Text files modified:
   branches/release/libs/variant/doc/reference/apply_visitor.xml | 63 +++++++++++++++++++++++++++++++++++++++
   branches/release/libs/variant/doc/reference/reference.xml | 5 +-
   branches/release/libs/variant/doc/tutorial/advanced.xml | 53 +++++++++++++++++++++++++++++++++
   branches/release/libs/variant/test/Jamfile.v2 | 1
   4 files changed, 119 insertions(+), 3 deletions(-)

Added: branches/release/boost/variant/multivisitors.hpp
==============================================================================
--- (empty file)
+++ branches/release/boost/variant/multivisitors.hpp 2013-05-14 14:19:39 EDT (Tue, 14 May 2013)
@@ -0,0 +1,143 @@
+// Boost.Varaint
+// Multivisitors defined here
+//
+// See http://www.boost.org for most recent version, including documentation.
+//
+// Copyright Antony Polukhin, 2013.
+//
+// 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).
+
+#ifndef BOOST_VARIANT_MULTIVISITORS_HPP
+#define BOOST_VARIANT_MULTIVISITORS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/variant.hpp>
+#include <boost/bind.hpp>
+
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/arithmetic/add.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
+
+#ifndef BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS
+# define BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 4
+#endif
+
+namespace boost {
+
+namespace detail { namespace variant {
+
+ template <class VisitorT, class Visitable1T, class Visitable2T>
+ struct two_variables_holder {
+ private:
+ VisitorT& visitor_;
+ Visitable1T& visitable1_;
+ Visitable2T& visitable2_;
+
+ // required to supress warnings and enshure that we do not copy
+ // this visitor
+ two_variables_holder& operator=(const two_variables_holder&);
+
+ public:
+ typedef BOOST_DEDUCED_TYPENAME VisitorT::result_type result_type;
+
+ explicit two_variables_holder(VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ , visitable1_(visitable1)
+ , visitable2_(visitable2)
+ {}
+
+#define BOOST_VARIANT_OPERATOR_BEG() \
+ return ::boost::apply_visitor( \
+ ::boost::bind<result_type>(boost::ref(visitor_), _1, _2 \
+ /**/
+
+#define BOOST_VARIANT_OPERATOR_END() \
+ ), visitable1_, visitable2_); \
+ /**/
+
+#define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \
+ BOOST_PP_COMMA() boost::ref( BOOST_PP_CAT(vis, n) ) \
+ /**/
+
+#define BOOST_VARIANT_VISIT(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n, 1), class VisitableUnwrapped)> \
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type) operator()( \
+ BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 1), VisitableUnwrapped, & vis) \
+ ) const \
+ { \
+ BOOST_VARIANT_OPERATOR_BEG() \
+ BOOST_PP_REPEAT(BOOST_PP_ADD(n, 1), BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \
+ BOOST_VARIANT_OPERATOR_END() \
+ } \
+ /**/
+
+BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, ~)
+#undef BOOST_VARIANT_OPERATOR_BEG
+#undef BOOST_VARIANT_OPERATOR_END
+#undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER
+#undef BOOST_VARIANT_VISIT
+
+ };
+
+ template <class VisitorT, class Visitable1T, class Visitable2T>
+ inline two_variables_holder<VisitorT, Visitable1T, Visitable2T> make_two_variables_holder(
+ VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2
+ ) BOOST_NOEXCEPT
+ {
+ return two_variables_holder<VisitorT, Visitable1T, Visitable2T>(visitor, visitable1, visitable2);
+ }
+
+ template <class VisitorT, class Visitable1T, class Visitable2T>
+ inline two_variables_holder<const VisitorT, Visitable1T, Visitable2T> make_two_variables_holder(
+ const VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2
+ ) BOOST_NOEXCEPT
+ {
+ return two_variables_holder<const VisitorT, Visitable1T, Visitable2T>(visitor, visitable1, visitable2);
+ }
+
+}} // namespace detail::variant
+
+#define BOOST_VARIANT_APPLY_VISITOR_BEG() \
+ return ::boost::apply_visitor( \
+ boost::detail::variant::make_two_variables_holder(visitor, var0 , var1), \
+ var2 \
+ /**/
+
+#define BOOST_VARIANT_APPLY_VISITOR_END() \
+ ); \
+ /**/
+
+#define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \
+ BOOST_PP_COMMA() BOOST_PP_CAT(var, BOOST_PP_ADD(n, 3)) \
+ /**/
+
+#define BOOST_VARIANT_VISIT(z, n, data) \
+ template <class Visitor BOOST_PP_COMMA() BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n, 3), class T)> \
+ inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(BOOST_DEDUCED_TYPENAME Visitor::result_type) apply_visitor( \
+ data BOOST_PP_COMMA() BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 3), T, & var) \
+ ) \
+ { \
+ BOOST_VARIANT_APPLY_VISITOR_BEG() \
+ BOOST_PP_REPEAT(n, BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \
+ BOOST_VARIANT_APPLY_VISITOR_END() \
+ } \
+ /**/
+
+BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, const Visitor& visitor)
+BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, Visitor& visitor)
+
+#undef BOOST_VARIANT_APPLY_VISITOR_BEG
+#undef BOOST_VARIANT_APPLY_VISITOR_END
+#undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER
+#undef BOOST_VARIANT_VISIT
+
+} // namespace boost
+
+#endif // BOOST_VARIANT_MULTIVISITORS_HPP
+

Modified: branches/release/libs/variant/doc/reference/apply_visitor.xml
==============================================================================
--- branches/release/libs/variant/doc/reference/apply_visitor.xml (original)
+++ branches/release/libs/variant/doc/reference/apply_visitor.xml 2013-05-14 14:19:39 EDT (Tue, 14 May 2013)
@@ -148,6 +148,60 @@
 
       <signature>
         <template>
+ <template-type-parameter name="MultiVisitor"/>
+ <template-type-parameter name="Variant1"/>
+ <template-type-parameter name="Variant2"/>
+ <template-type-parameter name="Variant3"/>
+ </template>
+
+ <type>typename MultiVisitor::result_type</type>
+
+ <parameter name="visitor">
+ <paramtype>MultiVisitor &amp;</paramtype>
+ </parameter>
+ <parameter name="operand1">
+ <paramtype>Variant1 &amp;</paramtype>
+ </parameter>
+ <parameter name="operand2">
+ <paramtype>Variant2 &amp;</paramtype>
+ </parameter>
+ <parameter name="operand3">
+ <paramtype>Variant3 &amp;</paramtype>
+ </parameter>
+ <parameter name="other_operands">
+ <paramtype>...</paramtype>
+ </parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="MultiVisitor"/>
+ <template-type-parameter name="Variant1"/>
+ <template-type-parameter name="Variant2"/>
+ <template-type-parameter name="Variant3"/>
+ </template>
+
+ <type>typename MultiVisitor::result_type</type>
+
+ <parameter name="visitor">
+ <paramtype>const MultiVisitor &amp;</paramtype>
+ </parameter>
+ <parameter name="operand1">
+ <paramtype>Variant1 &amp;</paramtype>
+ </parameter>
+ <parameter name="operand2">
+ <paramtype>Variant2 &amp;</paramtype>
+ </parameter>
+ <parameter name="operand3">
+ <paramtype>Variant3 &amp;</paramtype>
+ </parameter>
+ <parameter name="other_operands">
+ <paramtype>...</paramtype>
+ </parameter>
+ </signature>
+
+ <signature>
+ <template>
           <template-type-parameter name="Visitor"/>
         </template>
 
@@ -179,6 +233,13 @@
               the given <code><classname>variant</classname></code>
               operands.</listitem>
 
+ <listitem>Overloads accepting three or more operands invoke the
+ function call operator of the given visitor on the content of
+ the given <code><classname>variant</classname></code>
+ operands. Maximum amount of parameters controlled by
+ <code><emphasis role="bold"><macroname>BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS</macroname></emphasis></code>
+ macro. Those functions are actually defined in <xref linkend="header.boost.variant.multivisitors_hpp"/>.</listitem>
+
             <listitem>The overload accepting only a visitor returns a
               <classname alt="boost::apply_visitor_delayed_t">generic function object</classname>
               that accepts either one or two arguments and invokes
@@ -216,4 +277,4 @@
       </throws>
     </overloaded-function>
   </namespace>
-</header>
\ No newline at end of file
+</header>

Added: branches/release/libs/variant/doc/reference/multivisitor.xml
==============================================================================
--- (empty file)
+++ branches/release/libs/variant/doc/reference/multivisitor.xml 2013-05-14 14:19:39 EDT (Tue, 14 May 2013)
@@ -0,0 +1,88 @@
+<?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">
+<header name="boost/variant/multivisitors.hpp">
+ <using-namespace name="boost"/>
+
+ <para>Provides declarations of <functionname>apply_visitor</functionname> for three or more
+ <code><classname>variant</classname></code> parameters.</para>
+
+ <macro name="BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS">
+ <purpose>
+ <simpara>Controls maximum amount of <code><classname>variant</classname></code>
+ parameters for multi visistors. </simpara>
+ </purpose>
+
+ <description>
+ <para><emphasis role="bold">Note</emphasis>: Default amount is 4. Define it
+ to bigger value before including &lt;boost/variant/multivisitors.hpp&gt; to
+ increase maximum amount of <code><classname>variant</classname></code>
+ parameters for <functionname>apply_visitor</functionname>.</para>
+ </description>
+ </macro>
+
+ <namespace name="boost">
+ <overloaded-function name="apply_visitor /*three or more variant parameters*/">
+ <description>
+ <simpara>Allows compile-time checked type-safe application of the
+ given visitor to the content of the given variant, ensuring that all
+ types are handled by the visitor. See <functionname>apply_visitor</functionname>
+ for more information.</simpara>
+ </description>
+
+ <signature>
+ <template>
+ <template-type-parameter name="MultiVisitor"/>
+ <template-type-parameter name="Variant1"/>
+ <template-type-parameter name="Variant2"/>
+ <template-type-parameter name="Variant3"/>
+ </template>
+
+ <type>typename MultiVisitor::result_type</type>
+
+ <parameter name="visitor">
+ <paramtype>MultiVisitor &amp;</paramtype>
+ </parameter>
+ <parameter name="operand1">
+ <paramtype>Variant1 &amp;</paramtype>
+ </parameter>
+ <parameter name="operand2">
+ <paramtype>Variant2 &amp;</paramtype>
+ </parameter>
+ <parameter name="operand3">
+ <paramtype>Variant3 &amp;</paramtype>
+ </parameter>
+ <parameter name="other_operands">
+ <paramtype>...</paramtype>
+ </parameter>
+ </signature>
+
+ <signature>
+ <template>
+ <template-type-parameter name="MultiVisitor"/>
+ <template-type-parameter name="Variant1"/>
+ <template-type-parameter name="Variant2"/>
+ <template-type-parameter name="Variant3"/>
+ </template>
+
+ <type>typename MultiVisitor::result_type</type>
+
+ <parameter name="visitor">
+ <paramtype>const MultiVisitor &amp;</paramtype>
+ </parameter>
+ <parameter name="operand1">
+ <paramtype>Variant1 &amp;</paramtype>
+ </parameter>
+ <parameter name="operand2">
+ <paramtype>Variant2 &amp;</paramtype>
+ </parameter>
+ <parameter name="operand3">
+ <paramtype>Variant3 &amp;</paramtype>
+ </parameter>
+ <parameter name="other_operands">
+ <paramtype>...</paramtype>
+ </parameter>
+ </signature>
+ </overloaded-function>
+ </namespace>
+</header>

Modified: branches/release/libs/variant/doc/reference/reference.xml
==============================================================================
--- branches/release/libs/variant/doc/reference/reference.xml (original)
+++ branches/release/libs/variant/doc/reference/reference.xml 2013-05-14 14:19:39 EDT (Tue, 14 May 2013)
@@ -8,7 +8,7 @@
   <header name="boost/variant.hpp">
     <section id="variant.header.include-all">
       <para>This header exists simply as a convenience to the user, including
- all of the headers in the <code>boost/variant</code> directory.</para>
+ all of the headers in the <code>boost/variant</code> directory except &lt;boost/multivisiors.hpp&gt;.</para>
     </section>
   </header>
 
@@ -17,8 +17,9 @@
   <xi:include href="recursive_variant.xml"/>
   <xi:include href="recursive_wrapper.xml"/>
   <xi:include href="apply_visitor.xml"/>
+ <xi:include href="multivisitor.xml"/>
   <xi:include href="get.xml"/>
   <xi:include href="bad_visit.xml"/>
   <xi:include href="static_visitor.xml"/>
   <xi:include href="visitor_ptr.xml"/>
-</library-reference>
\ No newline at end of file
+</library-reference>

Modified: branches/release/libs/variant/doc/tutorial/advanced.xml
==============================================================================
--- branches/release/libs/variant/doc/tutorial/advanced.xml (original)
+++ branches/release/libs/variant/doc/tutorial/advanced.xml 2013-05-14 14:19:39 EDT (Tue, 14 May 2013)
@@ -355,4 +355,57 @@
 
 </section>
 
+<section id="variant.tutorial.multi-visitation">
+ <title>Multi visitation</title>
+
+ <para>Multi visitation extends the power and flexibility of visitation by allowing simultaneous
+ visitation of the content of three and more different <code>variant</code>
+ objects. Note that header for multi visitors shall be included separately.</para>
+
+ <para>Notably this feature requires that multi visitors are incompatible
+ with the visitor objects discussed in the tutorial above, as they must
+ operate on same amout of arguments that was passed to <code>apply_visitor</code>.
+ The following demonstrates the implementation of a multi visitor for three parameters:
+
+<programlisting>
+#include &lt;boost/variant/multivisitors.hpp&gt;
+
+typedef <classname>boost::variant</classname>&lt;int, double, bool&gt; bool_like_t;
+typedef <classname>boost::variant</classname>&lt;int, double&gt; arithmetics_t;
+
+struct if_visitor: public <classname>boost::static_visitor</classname>&lt;arithmetics_t&gt; {
+ template &lt;class T1, class T2&gt;
+ arithmetics_t operator()(bool b, T1 v1, T2 v2) const {
+ if (b) {
+ return v1;
+ } else {
+ return v2;
+ }
+ }
+};
+</programlisting>
+ </para>
+
+ <para>As expected, the visitor is applied to three <code>variant</code>
+ arguments by means of <code>apply_visitor</code>:
+
+<programlisting>
+bool_like_t v0(1), v1(true), v2(1.0);
+
+assert(
+ <functionname>boost::apply_visitor</functionname>(if_visitor(), v0, v1, v2)
+ ==
+ arithmetics_t(true)
+);
+</programlisting>
+ </para>
+
+ <para>Finally, we must note that multi visitation does not support
+ &quot;delayed&quot; form of
+ <code><functionname>apply_visitor</functionname></code>.
+ </para>
+
+</section>
+
+
 </section>

Modified: branches/release/libs/variant/test/Jamfile.v2
==============================================================================
--- branches/release/libs/variant/test/Jamfile.v2 (original)
+++ branches/release/libs/variant/test/Jamfile.v2 2013-05-14 14:19:39 EDT (Tue, 14 May 2013)
@@ -32,6 +32,7 @@
     [ run variant_reference_test.cpp ]
     [ run variant_comparison_test.cpp ]
     [ run variant_visit_test.cpp ]
+ [ run variant_multivisit_test.cpp ]
     [ run hash_variant_test.cpp ]
     [ run rvalue_test.cpp ]
    ;

Added: branches/release/libs/variant/test/variant_multivisit_test.cpp
==============================================================================
--- (empty file)
+++ branches/release/libs/variant/test/variant_multivisit_test.cpp 2013-05-14 14:19:39 EDT (Tue, 14 May 2013)
@@ -0,0 +1,124 @@
+//-----------------------------------------------------------------------------
+// boost-libs variant/test/variant_multivisit_test.cpp source file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2013
+// Antony Polukhin
+//
+// 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)
+
+#include "boost/config.hpp"
+#define BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 5
+#include "boost/variant/multivisitors.hpp"
+
+#include "boost/test/minimal.hpp"
+
+typedef boost::variant<char, unsigned char, signed char, unsigned short, int, unsigned int> variant6_t;
+
+struct test_visitor: boost::static_visitor<> {
+ // operators that shall not be called
+ template <class T1, class T2, class T3>
+ void operator()(T1, T2, T3) const
+ {
+ BOOST_CHECK(false);
+ }
+
+ template <class T1, class T2, class T3, class T4>
+ void operator()(T1, T2, T3, T4) const
+ {
+ BOOST_CHECK(false);
+ }
+
+ template <class T1, class T2, class T3, class T4, class T5>
+ void operator()(T1, T2, T3, T4, T5) const
+ {
+ BOOST_CHECK(false);
+ }
+
+ // operators that are OK to call
+ void operator()(char v0, unsigned char v1, signed char v2) const
+ {
+ BOOST_CHECK(v0 == 0);
+ BOOST_CHECK(v1 == 1);
+ BOOST_CHECK(v2 == 2);
+ }
+
+ void operator()(char v0, unsigned char v1, signed char v2, unsigned short v3) const
+ {
+ BOOST_CHECK(v0 == 0);
+ BOOST_CHECK(v1 == 1);
+ BOOST_CHECK(v2 == 2);
+ BOOST_CHECK(v3 == 3);
+ }
+
+ void operator()(char v0, unsigned char v1, signed char v2, unsigned short v3, int v4) const
+ {
+ BOOST_CHECK(v0 == 0);
+ BOOST_CHECK(v1 == 1);
+ BOOST_CHECK(v2 == 2);
+ BOOST_CHECK(v3 == 3);
+ BOOST_CHECK(v4 == 4);
+ }
+};
+
+typedef boost::variant<int, double, bool> bool_like_t;
+typedef boost::variant<int, double> arithmetics_t;
+
+struct if_visitor: public boost::static_visitor<arithmetics_t> {
+ template <class T1, class T2>
+ arithmetics_t operator()(bool b, T1 v1, T2 v2) const {
+ if (b) {
+ return v1;
+ } else {
+ return v2;
+ }
+ }
+};
+
+
+int test_main(int , char* [])
+{
+ test_visitor v;
+
+ variant6_t v_array6[6];
+ v_array6[0] = char(0);
+ v_array6[1] = static_cast<unsigned char>(1);
+ v_array6[2] = static_cast<signed char>(2);
+ v_array6[3] = static_cast<unsigned short>(3);
+ v_array6[4] = static_cast<int>(4);
+ v_array6[5] = static_cast<unsigned int>(5);
+
+ boost::apply_visitor(v, v_array6[0], v_array6[1], v_array6[2]);
+ boost::apply_visitor(test_visitor(), v_array6[0], v_array6[1], v_array6[2]);
+
+// Following test also pass, but requires many Gigabytes of RAM for compilation and compile for about 15 minutes
+//#define BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME
+#ifdef BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME
+ boost::apply_visitor(v, v_array6[0], v_array6[1], v_array6[2], v_array6[3]);
+ boost::apply_visitor(test_visitor(), v_array6[0], v_array6[1], v_array6[2], v_array6[3]);
+
+ boost::apply_visitor(v, v_array6[0], v_array6[1], v_array6[2], v_array6[3], v_array6[4]);
+ boost::apply_visitor(test_visitor(), v_array6[0], v_array6[1], v_array6[2], v_array6[3], v_array6[4]);
+#endif
+
+ bool_like_t v0(1), v1(true), v2(1.0);
+
+ BOOST_CHECK(
+ boost::apply_visitor(if_visitor(), v0, v1, v2)
+ ==
+ arithmetics_t(true)
+ );
+
+ /* Delayed multi visitation is not implemented
+ if_visitor if_vis;
+ BOOST_CHECK(
+ boost::apply_visitor(if_vis)(v0, v1, v2)
+ ==
+ arithmetics_t(true)
+ );
+ */
+ return boost::exit_success;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk