$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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 &</paramtype>
+        </parameter>
+        <parameter name="operand1">
+          <paramtype>Variant1 &</paramtype>
+        </parameter>
+        <parameter name="operand2">
+          <paramtype>Variant2 &</paramtype>
+        </parameter>
+        <parameter name="operand3">
+          <paramtype>Variant3 &</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 &</paramtype>
+        </parameter>
+        <parameter name="operand1">
+          <paramtype>Variant1 &</paramtype>
+        </parameter>
+        <parameter name="operand2">
+          <paramtype>Variant2 &</paramtype>
+        </parameter>
+        <parameter name="operand3">
+          <paramtype>Variant3 &</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 <boost/variant/multivisitors.hpp> 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 &</paramtype>
+        </parameter>
+        <parameter name="operand1">
+          <paramtype>Variant1 &</paramtype>
+        </parameter>
+        <parameter name="operand2">
+          <paramtype>Variant2 &</paramtype>
+        </parameter>
+        <parameter name="operand3">
+          <paramtype>Variant3 &</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 &</paramtype>
+        </parameter>
+        <parameter name="operand1">
+          <paramtype>Variant1 &</paramtype>
+        </parameter>
+        <parameter name="operand2">
+          <paramtype>Variant2 &</paramtype>
+        </parameter>
+        <parameter name="operand3">
+          <paramtype>Variant3 &</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 <boost/multivisiors.hpp>.</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 <boost/variant/multivisitors.hpp>
+
+typedef <classname>boost::variant</classname><int, double, bool> bool_like_t;
+typedef <classname>boost::variant</classname><int, double> arithmetics_t;
+
+struct if_visitor: public <classname>boost::static_visitor</classname><arithmetics_t> {
+    template <class T1, class T2>
+    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 
+    "delayed" 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;
+}