Hello community,

here is the log from the commit of package xtl for openSUSE:Factory checked in 
at 2020-09-16 19:38:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/xtl (Old)
 and      /work/SRC/openSUSE:Factory/.xtl.new.4249 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "xtl"

Wed Sep 16 19:38:49 2020 rev:3 rq:834832 version:0.6.18

Changes:
--------
--- /work/SRC/openSUSE:Factory/xtl/xtl.changes  2020-08-18 12:02:55.639422522 
+0200
+++ /work/SRC/openSUSE:Factory/.xtl.new.4249/xtl.changes        2020-09-16 
19:38:56.382772228 +0200
@@ -1,0 +2,9 @@
+Fri Sep  4 20:44:59 UTC 2020 - Dirk Mueller <[email protected]>
+
+- update to 0.6.18:
+  - Replaced throw with XTL_THROW to support disabling exceptions
+  - Implemented ``index_of`` for ``mpl::vector``
+  - Implemented multimethods pattern
+  - Implemented visitor pattern
+
+-------------------------------------------------------------------

Old:
----
  xtl-0.6.16.tar.gz

New:
----
  xtl-0.6.18.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ xtl.spec ++++++
--- /var/tmp/diff_new_pack.pHU7Y3/_old  2020-09-16 19:38:57.950773991 +0200
+++ /var/tmp/diff_new_pack.pHU7Y3/_new  2020-09-16 19:38:57.954773996 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           xtl
-Version:        0.6.16
+Version:        0.6.18
 Release:        0
 Summary:        The x template library
 License:        BSD-3-Clause

++++++ xtl-0.6.16.tar.gz -> xtl-0.6.18.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/CMakeLists.txt 
new/xtl-0.6.18/CMakeLists.txt
--- old/xtl-0.6.16/CMakeLists.txt       2020-08-11 11:44:33.000000000 +0200
+++ new/xtl-0.6.18/CMakeLists.txt       2020-09-02 11:10:31.000000000 +0200
@@ -56,6 +56,7 @@
     ${XTL_INCLUDE_DIR}/xtl/xmasked_value_meta.hpp
     ${XTL_INCLUDE_DIR}/xtl/xmasked_value.hpp
     ${XTL_INCLUDE_DIR}/xtl/xmeta_utils.hpp
+    ${XTL_INCLUDE_DIR}/xtl/xmultimethods.hpp
     ${XTL_INCLUDE_DIR}/xtl/xoptional_meta.hpp
     ${XTL_INCLUDE_DIR}/xtl/xoptional.hpp
     ${XTL_INCLUDE_DIR}/xtl/xoptional_sequence.hpp
@@ -65,6 +66,7 @@
     ${XTL_INCLUDE_DIR}/xtl/xtype_traits.hpp
     ${XTL_INCLUDE_DIR}/xtl/xvariant.hpp
     ${XTL_INCLUDE_DIR}/xtl/xvariant_impl.hpp
+    ${XTL_INCLUDE_DIR}/xtl/xvisitor.hpp
 )
 
 add_library(xtl INTERFACE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/docs/source/changelog.rst 
new/xtl-0.6.18/docs/source/changelog.rst
--- old/xtl-0.6.16/docs/source/changelog.rst    2020-08-11 11:44:33.000000000 
+0200
+++ new/xtl-0.6.18/docs/source/changelog.rst    2020-09-02 11:10:31.000000000 
+0200
@@ -7,6 +7,19 @@
 Changelog
 =========
 
+0.6.18
+------
+
+- Relaxed dimension constraint on multidispatcher
+- Replaced throw with XTL_THROW to support disabling exceptions
+
+0.6.17
+------
+
+- Implemented ``index_of`` for ``mpl::vector``
+- Implemented multimethods pattern
+- Implemented visitor pattern
+
 0.6.16
 ------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/include/xtl/xmeta_utils.hpp 
new/xtl-0.6.18/include/xtl/xmeta_utils.hpp
--- old/xtl-0.6.16/include/xtl/xmeta_utils.hpp  2020-08-11 11:44:33.000000000 
+0200
+++ new/xtl-0.6.18/include/xtl/xmeta_utils.hpp  2020-09-02 11:10:31.000000000 
+0200
@@ -11,6 +11,7 @@
 #define XTL_XMETA_UTILS_HPP
 
 #include <cstddef>
+#include <cstdint>
 #include <type_traits>
 
 #include "xfunctional.hpp"
@@ -224,6 +225,40 @@
         {
         };
 
+        /************
+         * index_of *
+         ************/
+
+        namespace detail
+        {
+            template <class L, class V>
+            struct index_of_impl;
+
+            template <template <class...> class L, class V>
+            struct index_of_impl<L<>, V>
+            {
+                static constexpr size_t value = SIZE_MAX;
+            };
+
+            template <template <class...> class L, class... T, class V>
+            struct index_of_impl<L<V, T...>, V>
+            {
+                static constexpr size_t value = 0u;
+            };
+
+            template <template <class...> class L, class U, class... T, class 
V>
+            struct index_of_impl<L<U, T...>, V>
+            {
+                static constexpr size_t tmp = index_of_impl<L<T...>, V>::value;
+                static constexpr size_t value = tmp == SIZE_MAX ? SIZE_MAX : 
1u + tmp;
+            };
+        }
+
+        template <class L, class T>
+        struct index_of : detail::index_of_impl<L, T>
+        {
+        };
+
         /************
          * contains *
          ************/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/include/xtl/xmultimethods.hpp 
new/xtl-0.6.18/include/xtl/xmultimethods.hpp
--- old/xtl-0.6.16/include/xtl/xmultimethods.hpp        1970-01-01 
01:00:00.000000000 +0100
+++ new/xtl-0.6.18/include/xtl/xmultimethods.hpp        2020-09-02 
11:10:31.000000000 +0200
@@ -0,0 +1,417 @@
+/***************************************************************************
+* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht          *
+* Copyright (c) QuantStack                                                 *
+*                                                                          *
+* Distributed under the terms of the BSD 3-Clause License.                 *
+*                                                                          *
+* The full license is in the file LICENSE, distributed with this software. *
+****************************************************************************/
+
+#ifndef XTL_MULTIMETHODS_HPP
+#define XTL_MULTIMETHODS_HPP
+
+#include <array>
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <typeindex>
+#include <type_traits>
+#include <vector>
+
+#include "xmeta_utils.hpp"
+
+namespace xtl
+{
+    // Loki's multimethods ported to modern C++ and generalized to N arguments
+    // Original implementation can be found at
+    // 
https://github.com/snaewe/loki-lib/blob/master/include/loki/MultiMethods.h
+
+    struct symmetric_dispatch {};
+    struct antisymmetric_dispatch {};
+
+    /*********************
+     * static_dispatcher *
+     *********************/
+
+    template
+    <
+        class executor,
+        class base_lhs,
+        class lhs_type_list,
+        class return_type = void,
+        class symmetric = antisymmetric_dispatch,
+        class base_rhs = base_lhs,
+        class rhs_type_list = lhs_type_list
+    >
+    class static_dispatcher
+    {
+    private:
+
+        template <class lhs_type, class rhs_type>
+        static return_type invoke_executor(lhs_type& lhs,
+                                           rhs_type& rhs,
+                                           executor& exec,
+                                           std::false_type)
+        {
+            return exec.run(lhs, rhs);
+        }
+
+        template <class lhs_type, class rhs_type>
+        static return_type invoke_executor(lhs_type& lhs,
+                                           rhs_type& rhs,
+                                           executor& exec,
+                                           std::true_type)
+        {
+            return exec.run(rhs, lhs);
+        }
+
+        template <class lhs_type>
+        static return_type dispatch_rhs(lhs_type& lhs,
+                                        base_rhs& rhs,
+                                        executor& exec,
+                                        mpl::vector<>)
+        {
+            return exec.on_error(lhs, rhs);
+        }
+
+        template <class lhs_type, class T, class... U>
+        static return_type dispatch_rhs(lhs_type& lhs,
+                                        base_rhs& rhs,
+                                        executor& exec,
+                                        mpl::vector<T, U...>)
+        {
+            if (T* p = dynamic_cast<T*>(&rhs))
+            {
+                constexpr size_t lhs_index = mpl::index_of<lhs_type_list, 
lhs_type>::value;
+                constexpr size_t rhs_index = mpl::index_of<rhs_type_list, 
T>::value;
+
+                using invoke_flag = std::integral_constant<bool,
+                    std::is_same<symmetric, symmetric_dispatch>::value && 
(rhs_index < lhs_index)>;
+                return invoke_executor(lhs, *p, exec, invoke_flag());
+            }
+            return dispatch_rhs(lhs, rhs, exec, mpl::vector<U...>());
+        }
+
+        static return_type dispatch_lhs(base_lhs& lhs,
+                                        base_rhs& rhs,
+                                        executor& exec,
+                                        mpl::vector<>)
+        {
+            return exec.on_error(lhs, rhs);
+        }
+
+        template <class T, class... U>
+        static return_type dispatch_lhs(base_lhs& lhs,
+                                        base_rhs& rhs,
+                                        executor& exec,
+                                        mpl::vector<T, U...>)
+        {
+            if (T* p = dynamic_cast<T*>(&lhs))
+            {
+                return dispatch_rhs(*p, rhs, exec, rhs_type_list());
+            }
+            return dispatch_lhs(lhs, rhs, exec, mpl::vector<U...>());
+        }
+
+    public:
+
+        static return_type dispatch(base_lhs& lhs, base_rhs& rhs, executor& 
exec)
+        {
+            return dispatch_lhs(lhs, rhs, exec, lhs_type_list());
+        }
+    };
+
+    // TODO: generalize to N-D with mpl::vector of mpl:vector
+    // Warning: this is hardcore ;)
+
+    /********************
+     * basic_dispatcher *
+     ********************/
+
+    template
+    <
+        class type_list,
+        class return_type,
+        class callback_type
+    >
+    class basic_dispatcher;
+
+    template
+    <
+        class return_type,
+        class callback_type,
+        class... B
+    >
+    class basic_dispatcher<mpl::vector<B...>, return_type, callback_type>
+    {
+    private:
+
+        using key_type = std::array<std::type_index, sizeof...(B)>;
+        using map_type = std::map<key_type, callback_type>;
+        map_type m_callback_map;
+
+        template <class... U>
+        key_type make_key() const
+        {
+            return {{std::type_index(typeid(U))...}};
+        }
+
+    public:
+
+        template <class... D>
+        void insert(callback_type&& cb)
+        {
+            static_assert(sizeof...(D) == sizeof...(B),
+                          "Number of callback arguments must match dispatcher 
dimension");
+            m_callback_map[make_key<D...>()] = std::move(cb);
+        }
+
+        template <class... D>
+        void erase()
+        {
+            static_assert(sizeof...(D) == sizeof...(B),
+                          "Number of callback arguments must match dispatcher 
dimension");
+            m_callback_map.erase(make_key<D...>());
+        }
+
+        inline return_type dispatch(B&... args) const
+        {
+            key_type k = {{std::type_index(typeid(args))...}};
+            auto it = m_callback_map.find(k);
+            if (it == m_callback_map.end())
+            {
+                XTL_THROW(std::runtime_error, "callback not found");
+            }
+            return (it->second)(args...);
+        }
+    };
+
+    /*************************
+     * basic_fast_dispatcher *
+     *************************/
+
+#define XTL_IMPLEMENT_INDEXABLE_CLASS()         \
+    static size_t& get_class_static_index()     \
+    {                                           \
+        static size_t index = SIZE_MAX;         \
+        return index;                           \
+    }                                           \
+    virtual size_t get_class_index() const      \
+    {                                           \
+        return get_class_static_index();        \
+    }
+
+    namespace detail
+    {
+        template <class T>
+        class recursive_container_impl : private std::vector<T>
+        {
+        public:
+
+            using base_type = std::vector<T>;
+
+            using base_type::base_type;
+            using base_type::operator[];
+            using base_type::size;
+            using base_type::resize;
+        };
+
+        template <class callback_type, size_t level>
+        class recursive_container
+            : public 
recursive_container_impl<recursive_container<callback_type, level-1>>
+        {
+        };
+
+        template <class callback>
+        class recursive_container<callback, 0>
+            : public recursive_container_impl<callback>
+        {
+        };
+      }
+
+    template
+    <
+        class type_list,
+        class return_type,
+        class callback_type
+    >
+    class basic_fast_dispatcher;
+
+    template
+    <
+        class return_type,
+        class callback_type,
+        class... B
+    >
+    class basic_fast_dispatcher<mpl::vector<B...>, return_type, callback_type>
+    {
+    private:
+
+        static constexpr size_t nb_args = sizeof...(B);
+
+        using storage_type = detail::recursive_container<callback_type, 
sizeof...(B) - 1>;
+        using index_type = std::array<size_t, nb_args>;
+        using index_ref_type = std::array<std::reference_wrapper<size_t>, 
nb_args>;
+
+        storage_type m_callbacks;
+        size_t m_next_index;
+
+        template <size_t I, class C>
+        void resize_container(C& c, const index_ref_type& index)
+        {
+            size_t& idx = index[I];
+            if (idx == SIZE_MAX)
+            {
+                c.resize(++m_next_index);
+                idx = c.size() - 1u;
+            }
+            else if(c.size() <= idx)
+            {
+                c.resize(idx + 1u);
+            }
+        }
+
+        template <size_t I, class C>
+        std::enable_if_t<I + 1 == nb_args>
+        insert_impl(callback_type&& cb, C& c, const index_ref_type& index)
+        {
+            resize_container<I>(c, index);
+            c[index[I]] = std::move(cb);
+        }
+
+        template <size_t I, class C>
+        std::enable_if_t<I + 1 != nb_args>
+        insert_impl(callback_type&& cb, C& c, const index_ref_type& index)
+        {
+            resize_container<I>(c, index);
+            insert_impl<I+1>(std::move(cb), c[index[I]], index);
+        }
+
+        template <size_t I, class C>
+        void check_size(C& c, const index_type& index) const
+        {
+            if (index[I] >= c.size())
+            {
+                XTL_THROW(std::runtime_error, "callback not found");
+            }
+        }
+
+        template <size_t I, class C>
+        std::enable_if_t<I + 1 == nb_args, return_type>
+        dispatch_impl(C& c, const index_type& index, B&... args) const
+        {
+            check_size<I>(c, index);
+            return c[index[I]](args...);
+        }
+
+        template <size_t I, class C>
+        std::enable_if_t<I + 1 != nb_args, return_type>
+        dispatch_impl(C& c, const index_type& index, B&... args) const
+        {
+            check_size<I>(c, index);
+            return dispatch_impl<I+1>(c[index[I]], index, args...);
+        }
+
+    public:
+
+        inline basic_fast_dispatcher()
+            : m_next_index(0)
+        {
+        }
+
+        template <class... D>
+        void insert(callback_type&& cb)
+        {
+            static_assert(sizeof...(D) == sizeof...(B),
+                          "Number of callback arguments must match dispatcher 
dimension");
+            index_ref_type index = 
{{std::ref(D::get_class_static_index())...}};
+            insert_impl<0>(std::move(cb), m_callbacks, index);
+        }
+
+        inline return_type dispatch(B&... args) const
+        {
+            index_type index = {{args.get_class_index()...}};
+            return dispatch_impl<0>(m_callbacks, index, args...);
+        }
+    };
+
+    /******************************
+     * dynamic and static casters *
+     ******************************/
+
+    template <class T, class F>
+    struct static_caster
+    {
+        static T& cast(F& f)
+        {
+            return static_cast<T&>(f);
+        }
+    };
+
+    template <class T, class F>
+    struct dynamic_caster
+    {
+        static T& cast(F& f)
+        {
+            return dynamic_cast<T&>(f);
+        }
+    };
+
+    /**********************
+     * functor_dispatcher *
+     **********************/
+
+    template
+    <
+        class type_list,
+        class return_type,
+        template <class, class> class casting_policy = dynamic_caster,
+        template <class, class, class> class dispatcher = basic_dispatcher
+    >
+    class functor_dispatcher;
+
+    template
+    <
+        class return_type, 
+        template <class, class> class casting_policy,
+        template <class, class, class> class dispatcher,
+        class... B
+    >
+    class functor_dispatcher<mpl::vector<B...>, return_type, casting_policy, 
dispatcher>
+    {
+    private:
+
+        using functor_type = std::function<return_type (B&...)>;
+        using backend = dispatcher<mpl::vector<B...>,
+                                   return_type,
+                                   functor_type>;
+        backend m_backend;
+
+    public:
+
+        template <class... D, class Fun>
+        void insert(const Fun& fun)
+        {
+            functor_type f([fun](B&... args) -> return_type
+            {
+                return fun(casting_policy<D&, B&>::cast(args)...);
+            });
+            m_backend.template insert<D...>(std::move(f));
+        }
+
+        template <class... D>
+        void erase()
+        {
+            m_backend.template erase<D...>();
+        }
+
+        inline return_type dispatch(B&... args) const
+        {
+            return m_backend.dispatch(args...);
+        }
+    };
+
+}
+
+#endif
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/include/xtl/xtl_config.hpp 
new/xtl-0.6.18/include/xtl/xtl_config.hpp
--- old/xtl-0.6.16/include/xtl/xtl_config.hpp   2020-08-11 11:44:33.000000000 
+0200
+++ new/xtl-0.6.18/include/xtl/xtl_config.hpp   2020-09-02 11:10:31.000000000 
+0200
@@ -12,7 +12,7 @@
 
 #define XTL_VERSION_MAJOR 0
 #define XTL_VERSION_MINOR 6
-#define XTL_VERSION_PATCH 16
+#define XTL_VERSION_PATCH 18
 
 #ifndef __has_feature
 #define __has_feature(x) 0
@@ -26,4 +26,14 @@
 #define XTL_NO_EXCEPTIONS
 #endif
 
+#if defined(XTL_NO_EXCEPTIONS)
+#define XTL_THROW(_, msg)              \
+    {                                  \
+        std::cerr << msg << std::endl; \
+        std::abort();                  \
+    }
+#else
+#define XTL_THROW(exception, msg) throw exception(msg)
+#endif
+
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/include/xtl/xvisitor.hpp 
new/xtl-0.6.18/include/xtl/xvisitor.hpp
--- old/xtl-0.6.16/include/xtl/xvisitor.hpp     1970-01-01 01:00:00.000000000 
+0100
+++ new/xtl-0.6.18/include/xtl/xvisitor.hpp     2020-09-02 11:10:31.000000000 
+0200
@@ -0,0 +1,195 @@
+/***************************************************************************
+* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht          *
+* Copyright (c) QuantStack                                                 *
+*                                                                          *
+* Distributed under the terms of the BSD 3-Clause License.                 *
+*                                                                          *
+* The full license is in the file LICENSE, distributed with this software. *
+****************************************************************************/
+
+#ifndef XTL_VISITOR_HPP
+#define XTL_VISITOR_HPP
+
+#include <stdexcept>
+#include "xmeta_utils.hpp"
+
+namespace xtl
+{
+    // Loki's visitor ported to C++14
+    // Original implementation can be found at:
+    // https://github.com/snaewe/loki-lib/blob/master/include/loki/Visitor.h
+
+    /****************
+     * base_visitor *
+     ****************/
+
+    class base_visitor
+    {
+    public:
+
+        virtual ~base_visitor() = default;
+    };
+
+    /***********
+     * visitor *
+     ***********/
+
+    template <class T, class R = void, bool is_const = true>
+    class visitor
+    {
+    public:
+
+        using return_type = R;
+        using param_type = std::conditional_t<is_const, const T, T>;
+
+        virtual ~visitor() = default;
+
+        virtual return_type visit(param_type&) = 0;
+    };
+
+    template <class R, bool is_const>
+    class visitor<mpl::vector<>, R, is_const>
+    {
+    };
+
+    template <class R, bool is_const, class T, class... U>
+    class visitor<mpl::vector<T, U...>, R, is_const>
+        : public visitor<T, R, is_const>
+        , public visitor<mpl::vector<U...>, R, is_const>
+    {
+    };
+
+    /**********************
+     * catch_all policies *
+     **********************/
+
+    template <class R, class T>
+    struct default_catch_all
+    {
+        static R on_unknown_visitor(T&, base_visitor&)
+        {
+            return R();
+        }
+    };
+
+    template <class R, class T>
+    struct throwing_catch_all
+    {
+        static R on_unknown_visitor(T&, base_visitor&)
+        {
+            XTL_THROW(std::runtime_error, "Unknown visited type");
+        }
+    };
+
+    /******************
+     * base_visitable *
+     ******************/
+
+    template
+    <
+        class R = void,
+        bool const_visitable = false,
+        template <class, class> class catch_all = default_catch_all
+    >
+    class base_visitable;
+
+    template <class R, template <class, class> class catch_all>
+    class base_visitable<R, false, catch_all>
+    {
+    public:
+
+        using return_type = R;
+
+        virtual ~base_visitable() = default;
+        virtual return_type accept(base_visitor&) = 0;
+
+    protected:
+
+        template <class T>
+        static return_type accept_impl(T& visited, base_visitor& vis)
+        {
+            if (auto* p = dynamic_cast<visitor<T, R, false>*>(&vis))
+            {
+                return p->visit(visited);
+            }
+            return catch_all<R, T>::on_unknown_visitor(visited, vis);
+        }
+    };
+
+    template <class R, template <class, class> class catch_all>
+    class base_visitable<R, true, catch_all>
+    {
+    public:
+
+        using return_type = R;
+
+        virtual ~base_visitable() = default;
+        virtual return_type accept(base_visitor&) const = 0;
+
+    protected:
+
+        template <class T>
+        static return_type accept_impl(const T& visited, base_visitor& vis)
+        {
+            if (auto* p = dynamic_cast<visitor<T, R, true>*>(&vis))
+            {
+                return p->visit(visited);
+            }
+            return catch_all<R, const T>::on_unknown_visitor(visited, vis);
+        }
+    };
+
+    /************************
+     * XTL_DEFINE_VISITABLE *
+     ************************/
+
+#define XTL_DEFINE_VISITABLE() \
+    return_type accept(::xtl::base_visitor& vis) override \
+    { return accept_impl(*this, vis); }
+
+#define XTL_DEFINE_CONST_VISITABLE() \
+    return_type accept(::xtl::base_visitor& vis) const override \
+    { return accept_impl(*this, vis); }
+
+    /******************
+     * cyclic_visitor *
+     ******************/
+
+    template <class T, class R, bool is_const = true>
+    class cyclic_visitor;
+
+    template <class R, bool is_const, class... T>
+    class cyclic_visitor<mpl::vector<T...>, R, is_const>
+        : public visitor<mpl::vector<T...>, R, is_const>
+    {
+    public:
+
+        using return_type = R;
+
+        template <class V>
+        return_type generic_visit(V& visited)
+        {
+            visitor<std::remove_const_t<V>, return_type, is_const>& sub_obj = 
*this;
+            return sub_obj.visit(visited);
+        }
+    };
+
+    /*******************************
+     * XTL_DEFINE_CYCLIC_VISITABLE *
+     *******************************/
+
+#define XTL_DEFINE_CYCLIC_VISITABLE(some_visitor)                     \
+    virtual some_visitor::return_type accept(some_visitor& vis)       \
+    {                                                                 \
+        return vis.generic_visit(*this);                              \
+    }
+
+#define XTL_DEFINE_CONST_CYCLIC_VISITABLE(some_visitor)               \
+    virtual some_visitor::return_type accept(some_visitor& vis) const \
+    {                                                                 \
+        return vis.generic_visit(*this);                              \
+    }
+}
+
+#endif
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/test/CMakeLists.txt 
new/xtl-0.6.18/test/CMakeLists.txt
--- old/xtl-0.6.16/test/CMakeLists.txt  2020-08-11 11:44:33.000000000 +0200
+++ new/xtl-0.6.18/test/CMakeLists.txt  2020-09-02 11:10:31.000000000 +0200
@@ -127,11 +127,13 @@
     test_xiterator_base.cpp
     test_xmasked_value.cpp
     test_xmeta_utils.cpp
+    test_xmultimethods.cpp
     test_xoptional.cpp
     test_xsequence.cpp
     test_xtype_traits.cpp
     test_xproxy_wrapper.cpp
     test_xvariant.cpp
+    test_xvisitor.cpp
 )
 
 if(nlohmann_json_FOUND)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/test/test_xmeta_utils.cpp 
new/xtl-0.6.18/test/test_xmeta_utils.cpp
--- old/xtl-0.6.16/test/test_xmeta_utils.cpp    2020-08-11 11:44:33.000000000 
+0200
+++ new/xtl-0.6.18/test/test_xmeta_utils.cpp    2020-09-02 11:10:31.000000000 
+0200
@@ -88,6 +88,20 @@
         EXPECT_FALSE(res3);
     }
 
+    TEST(mpl, index_of)
+    {
+        using type1 = mpl::vector<int, double, float>;
+        std::size_t res1 = mpl::index_of<type1, int>::value;
+        std::size_t res2 = mpl::index_of<type1, double>::value;
+        std::size_t res3 = mpl::index_of<type1, float>::value;
+        std::size_t res4 = mpl::index_of<type1, short>::value;
+
+        EXPECT_EQ(res1, 0u);
+        EXPECT_EQ(res2, 1u);
+        EXPECT_EQ(res3, 2u);
+        EXPECT_EQ(res4, SIZE_MAX);
+    }
+
     TEST(mpl, front)
     {
         using type = mpl::front_t<variant_t>;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/test/test_xmultimethods.cpp 
new/xtl-0.6.18/test/test_xmultimethods.cpp
--- old/xtl-0.6.16/test/test_xmultimethods.cpp  1970-01-01 01:00:00.000000000 
+0100
+++ new/xtl-0.6.18/test/test_xmultimethods.cpp  2020-09-02 11:10:31.000000000 
+0200
@@ -0,0 +1,245 @@
+/***************************************************************************
+* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht          *
+* Copyright (c) QuantStack                                                 *
+*                                                                          *
+* Distributed under the terms of the BSD 3-Clause License.                 *
+*                                                                          *
+* The full license is in the file LICENSE, distributed with this software. *
+****************************************************************************/
+
+#include <iostream>
+#include "xtl/xmultimethods.hpp"
+
+#include "gtest/gtest.h"
+
+namespace xtl
+{
+    enum class shape_id
+    {
+        unknown_id,
+        rectangle_id,
+        circle_id,
+        triangle_id
+    };
+
+    class shape
+    {
+    public:
+        
+        XTL_IMPLEMENT_INDEXABLE_CLASS()
+        
+        virtual ~shape() = default;
+
+        shape(const shape&) = delete;
+        shape(shape&&) = delete;
+
+        shape& operator=(const shape&) = delete;
+        shape& operator=(shape&&) = delete;
+
+    protected:
+
+        shape() = default;
+    };
+
+    template <shape_id id>
+    class shape_impl : public shape
+    {
+    public:
+        
+        XTL_IMPLEMENT_INDEXABLE_CLASS()
+
+        shape_impl() = default;
+        virtual ~shape_impl() = default;
+
+        shape_id get_id() const
+        {
+            return id;
+        }
+    };
+
+    using rectangle = shape_impl<shape_id::rectangle_id>;
+    using circle = shape_impl<shape_id::circle_id>;
+    using triangle = shape_impl<shape_id::triangle_id>;
+
+    using dispatch_return_type = std::pair<shape_id, shape_id>;
+
+    namespace
+    {
+        template <class T1, class T2>
+        dispatch_return_type dispatch_shape_impl(const T1& t1, const T2& t2)
+        {
+            return std::make_pair(t1.get_id(), t2.get_id());
+        }
+
+#define DEFINE_DISPATCH_SHAPE(T1, T2) \
+        dispatch_return_type dispatch_##T1##_##T2(const T1& t1, const T2& t2) \
+        { return dispatch_shape_impl(t1, t2); }
+
+        DEFINE_DISPATCH_SHAPE(rectangle, circle)
+        DEFINE_DISPATCH_SHAPE(rectangle, triangle)
+        DEFINE_DISPATCH_SHAPE(circle, rectangle)
+        DEFINE_DISPATCH_SHAPE(circle, triangle)
+        DEFINE_DISPATCH_SHAPE(triangle, rectangle)
+        DEFINE_DISPATCH_SHAPE(triangle, circle)
+    }
+
+    class dispatch_tester
+    {
+    public:
+
+        using return_type = dispatch_return_type;
+
+        template <class T1, class T2>
+        return_type run(const T1& t1, const T2& t2) const
+        {
+            return dispatch_shape_impl(t1, t2);
+        }
+
+        return_type on_error(const shape&, const shape&) const
+        {
+            return std::make_pair(shape_id::unknown_id, shape_id::unknown_id);
+        }
+    };
+
+    TEST(multimethods, static_dispatch)
+    {
+        using return_type = dispatch_tester::return_type;
+        using dispatcher_type = static_dispatcher
+        <
+            dispatch_tester,
+            const shape,
+            mpl::vector<const rectangle, const circle, const triangle>,
+            return_type
+        >;
+        rectangle r;
+        circle c;
+        triangle t;
+        shape* p1 = &r;
+        shape* p2 = &c;
+        shape* p3 = &t;
+        dispatch_tester tester;
+
+        return_type r1 = dispatcher_type::dispatch(*p1, *p2, tester);
+        return_type r2 = dispatcher_type::dispatch(*p1, *p3, tester);
+        return_type r3 = dispatcher_type::dispatch(*p2, *p1, tester);
+        return_type r4 = dispatcher_type::dispatch(*p2, *p3, tester);
+        return_type r5 = dispatcher_type::dispatch(*p3, *p1, tester);
+        return_type r6 = dispatcher_type::dispatch(*p3, *p2, tester);
+
+        EXPECT_EQ(r1, return_type(shape_id::rectangle_id, 
shape_id::circle_id));
+        EXPECT_EQ(r2, return_type(shape_id::rectangle_id, 
shape_id::triangle_id));
+        EXPECT_EQ(r3, return_type(shape_id::circle_id, 
shape_id::rectangle_id));
+        EXPECT_EQ(r4, return_type(shape_id::circle_id, shape_id::triangle_id));
+        EXPECT_EQ(r5, return_type(shape_id::triangle_id, 
shape_id::rectangle_id));
+        EXPECT_EQ(r6, return_type(shape_id::triangle_id, shape_id::circle_id));
+    }
+
+    TEST(multimethods, static_dispatch_symmetry)
+    {
+        using return_type = dispatch_tester::return_type;
+        using dispatcher_type = static_dispatcher
+        <
+            dispatch_tester,
+            const shape,
+            mpl::vector<const rectangle, const circle, const triangle>,
+            return_type,
+            symmetric_dispatch
+        >;
+        rectangle r;
+        circle c;
+        triangle t;
+        shape* p1 = &r;
+        shape* p2 = &c;
+        shape* p3 = &t;
+        dispatch_tester tester;
+
+        return_type r1 = dispatcher_type::dispatch(*p1, *p2, tester);
+        return_type r2 = dispatcher_type::dispatch(*p1, *p3, tester);
+        return_type r3 = dispatcher_type::dispatch(*p2, *p1, tester);
+        return_type r4 = dispatcher_type::dispatch(*p2, *p3, tester);
+        return_type r5 = dispatcher_type::dispatch(*p3, *p1, tester);
+        return_type r6 = dispatcher_type::dispatch(*p3, *p2, tester);
+
+        EXPECT_EQ(r1, return_type(shape_id::rectangle_id, 
shape_id::circle_id));
+        EXPECT_EQ(r2, return_type(shape_id::rectangle_id, 
shape_id::triangle_id));
+        EXPECT_EQ(r3, return_type(shape_id::rectangle_id, 
shape_id::circle_id));
+        EXPECT_EQ(r4, return_type(shape_id::circle_id, shape_id::triangle_id));
+        EXPECT_EQ(r5, return_type(shape_id::rectangle_id, 
shape_id::triangle_id));
+        EXPECT_EQ(r6, return_type(shape_id::circle_id, shape_id::triangle_id));
+    }
+
+    template <class D>
+    void test_function_dispatcher()
+    {
+        using dispatcher_type = D;
+        using return_type = dispatch_return_type;
+        dispatcher_type d;
+        d.template insert<const rectangle, const 
circle>(&dispatch_rectangle_circle);
+        d.template insert<const rectangle, const 
triangle>(&dispatch_rectangle_triangle);
+        d.template insert<const circle, const 
rectangle>(&dispatch_circle_rectangle);
+        d.template insert<const circle, const 
triangle>(&dispatch_circle_triangle);
+        d.template insert<const triangle, const 
rectangle>(&dispatch_triangle_rectangle);
+        d.template insert<const triangle, const 
circle>(&dispatch_triangle_circle);
+
+        rectangle r;
+        circle c;
+        triangle t;
+        shape* p1 = &r;
+        shape* p2 = &c;
+        shape* p3 = &t;
+
+        return_type r1 = d.dispatch(*p1, *p2);
+        return_type r2 = d.dispatch(*p1, *p3);
+        return_type r3 = d.dispatch(*p2, *p1);
+        return_type r4 = d.dispatch(*p2, *p3);
+        return_type r5 = d.dispatch(*p3, *p1);
+        return_type r6 = d.dispatch(*p3, *p2);
+
+        EXPECT_EQ(r1, return_type(shape_id::rectangle_id, 
shape_id::circle_id));
+        EXPECT_EQ(r2, return_type(shape_id::rectangle_id, 
shape_id::triangle_id));
+        EXPECT_EQ(r3, return_type(shape_id::circle_id, 
shape_id::rectangle_id));
+        EXPECT_EQ(r4, return_type(shape_id::circle_id, shape_id::triangle_id));
+        EXPECT_EQ(r5, return_type(shape_id::triangle_id, 
shape_id::rectangle_id));
+        EXPECT_EQ(r6, return_type(shape_id::triangle_id, shape_id::circle_id));
+    }
+
+    TEST(multimethods, function_dispatcher)
+    {
+        using return_type = dispatch_return_type;
+        using dispatcher_type = functor_dispatcher
+        <
+            mpl::vector<const shape, const shape>,
+            return_type
+        >;
+
+        test_function_dispatcher<dispatcher_type>();
+    }
+
+    TEST(multimethods, function_dispatcher_static_cast)
+    {
+        using return_type = dispatch_return_type;
+        using dispatcher_type = functor_dispatcher
+        <
+            mpl::vector<const shape, const shape>,
+            return_type,
+            static_caster
+        >;
+
+        test_function_dispatcher<dispatcher_type>();
+    }
+
+    TEST(multimethods, fast_function_dispatcher)
+    {
+        using return_type = dispatch_return_type;
+        using dispatcher_type = functor_dispatcher
+        <
+            mpl::vector<const shape, const shape>,
+            return_type,
+            static_caster,
+            basic_fast_dispatcher
+        >;
+
+        test_function_dispatcher<dispatcher_type>();
+    }
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/xtl-0.6.16/test/test_xvisitor.cpp 
new/xtl-0.6.18/test/test_xvisitor.cpp
--- old/xtl-0.6.16/test/test_xvisitor.cpp       1970-01-01 01:00:00.000000000 
+0100
+++ new/xtl-0.6.18/test/test_xvisitor.cpp       2020-09-02 11:10:31.000000000 
+0200
@@ -0,0 +1,236 @@
+/***************************************************************************
+* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht          *
+* Copyright (c) QuantStack                                                 *
+*                                                                          *
+* Distributed under the terms of the BSD 3-Clause License.                 *
+*                                                                          *
+* The full license is in the file LICENSE, distributed with this software. *
+****************************************************************************/
+
+#include "xtl/xvisitor.hpp"
+
+#include "gtest/gtest.h"
+
+namespace xtl
+{
+    class root : public base_visitable<int, false>
+    {
+    public:
+
+        XTL_DEFINE_VISITABLE()
+    };
+
+    class leaf_one : public root
+    {
+    public:
+
+        XTL_DEFINE_VISITABLE()
+    };
+
+    class leaf_two : public root
+    {
+    public:
+
+        XTL_DEFINE_VISITABLE()
+    };
+
+    class acyclic_visitor_tester
+        : public base_visitor
+        , public visitor<mpl::vector<leaf_one, leaf_two>, int, false>
+    {
+    public:
+
+        int visit(leaf_one&) override
+        {
+            return 1;
+        }
+
+        int visit(leaf_two&) override
+        {
+            return 2;
+        }
+    };
+
+    TEST(visitor, acyclic_visitor)
+    {
+        leaf_one l1;
+        leaf_two l2;
+        root* r1 = &l1;
+        root* r2 = &l2;
+
+        acyclic_visitor_tester t;
+
+        int res1 = r1->accept(t);
+        EXPECT_EQ(res1, 1);
+
+        int res2 = r2->accept(t);
+        EXPECT_EQ(res2, 2);
+    }
+
+    class const_root : public base_visitable<int, true>
+    {
+    public:
+
+        XTL_DEFINE_CONST_VISITABLE()
+    };
+
+    class const_leaf_one : public const_root
+    {
+    public:
+
+        XTL_DEFINE_CONST_VISITABLE()
+    };
+
+    class const_leaf_two : public const_root
+    {
+    public:
+
+        XTL_DEFINE_CONST_VISITABLE()
+    };
+
+    class const_acyclic_visitor_tester
+        : public base_visitor
+        , public visitor<mpl::vector<const_leaf_one, const_leaf_two>, int, 
true>
+    {
+    public:
+
+        int visit(const const_leaf_one&) override
+        {
+            return 1;
+        }
+
+        int visit(const const_leaf_two&) override
+        {
+            return 2;
+        }
+    };
+
+    TEST(visitor, const_acyclic_visitor)
+    {
+        const_leaf_one l1;
+        const_leaf_two l2;
+        const_root* r1 = &l1;
+        const_root* r2 = &l2;
+
+        const_acyclic_visitor_tester t;
+
+        int res1 = r1->accept(t);
+        EXPECT_EQ(res1, 1);
+
+        int res2 = r2->accept(t);
+        EXPECT_EQ(res2, 2);
+    }
+
+    class cleaf_one;
+    class cleaf_two;
+
+    class cyclic_visitor_tester
+        : public cyclic_visitor<mpl::vector<cleaf_one, cleaf_two>, int, false>
+    {
+    public:
+
+        int visit(cleaf_one&) override
+        {
+            return 1;
+        }
+
+        int visit(cleaf_two&) override
+        {
+            return 2;
+        }
+    };
+
+    class croot
+    {
+    public:
+
+        virtual int accept(cyclic_visitor_tester&) = 0;
+    };
+
+    class cleaf_one : public croot
+    {
+    public:
+
+        XTL_DEFINE_CYCLIC_VISITABLE(cyclic_visitor_tester)
+    };
+
+    class cleaf_two : public croot
+    {
+    public:
+
+        XTL_DEFINE_CYCLIC_VISITABLE(cyclic_visitor_tester)
+    };
+    
+    TEST(visitor, cyclic_visitor)
+    {
+        cleaf_one l1;
+        cleaf_two l2;
+        croot* r1 = &l1;
+        croot* r2 = &l2;
+
+        cyclic_visitor_tester t;
+
+        int res1 = r1->accept(t);
+        EXPECT_EQ(res1, 1);
+
+        int res2 = r2->accept(t);
+        EXPECT_EQ(res2, 2);
+    }
+
+    class ccleaf_one;
+    class ccleaf_two;
+
+    class ccyclic_visitor_tester
+        : public cyclic_visitor<mpl::vector<ccleaf_one, ccleaf_two>, int, true>
+    {
+    public:
+
+        int visit(const ccleaf_one&) override
+        {
+            return 1;
+        }
+
+        int visit(const ccleaf_two&) override
+        {
+            return 2;
+        }
+    };
+
+    class ccroot
+    {
+    public:
+
+        virtual int accept(ccyclic_visitor_tester&) const = 0;
+    };
+
+    class ccleaf_one : public ccroot
+    {
+    public:
+
+        XTL_DEFINE_CONST_CYCLIC_VISITABLE(ccyclic_visitor_tester)
+    };
+
+    class ccleaf_two : public ccroot
+    {
+    public:
+
+        XTL_DEFINE_CONST_CYCLIC_VISITABLE(ccyclic_visitor_tester)
+    };
+    
+    TEST(visitor, const_cyclic_visitor)
+    {
+        ccleaf_one l1;
+        ccleaf_two l2;
+        ccroot* r1 = &l1;
+        ccroot* r2 = &l2;
+
+        ccyclic_visitor_tester t;
+
+        int res1 = r1->accept(t);
+        EXPECT_EQ(res1, 1);
+
+        int res2 = r2->accept(t);
+        EXPECT_EQ(res2, 2);
+    }
+}
+


Reply via email to