You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			659 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
			
		
		
	
	
			659 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
// This file is part of OpenCV project.
 | 
						|
// It is subject to the license terms in the LICENSE file found in the top-level directory
 | 
						|
// of this distribution and at http://opencv.org/license.html.
 | 
						|
//
 | 
						|
// Copyright (C) 2018 Intel Corporation
 | 
						|
 | 
						|
 | 
						|
#ifndef OPENCV_GAPI_UTIL_VARIANT_HPP
 | 
						|
#define OPENCV_GAPI_UTIL_VARIANT_HPP
 | 
						|
 | 
						|
#include <array>
 | 
						|
#include <type_traits>
 | 
						|
 | 
						|
#include <opencv2/gapi/util/compiler_hints.hpp>
 | 
						|
#include <opencv2/gapi/util/throw.hpp>
 | 
						|
#include <opencv2/gapi/util/util.hpp> // max_of_t
 | 
						|
#include <opencv2/gapi/util/type_traits.hpp>
 | 
						|
 | 
						|
// A poor man's `variant` implementation, incompletely modeled against C++17 spec.
 | 
						|
namespace cv
 | 
						|
{
 | 
						|
namespace util
 | 
						|
{
 | 
						|
    namespace detail
 | 
						|
    {
 | 
						|
        template<std::size_t I, typename Target, typename First, typename... Remaining>
 | 
						|
        struct type_list_index_helper
 | 
						|
        {
 | 
						|
            static const constexpr bool is_same = std::is_same<Target, First>::value;
 | 
						|
            static const constexpr std::size_t value =
 | 
						|
                std::conditional<is_same, std::integral_constant<std::size_t, I>, type_list_index_helper<I + 1, Target, Remaining...>>::type::value;
 | 
						|
        };
 | 
						|
 | 
						|
        template<std::size_t I, typename Target, typename First>
 | 
						|
        struct type_list_index_helper<I, Target, First>
 | 
						|
        {
 | 
						|
            static_assert(std::is_same<Target, First>::value, "Type not found");
 | 
						|
            static const constexpr std::size_t value = I;
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename Target, typename... Types>
 | 
						|
    struct type_list_index
 | 
						|
    {
 | 
						|
        static const constexpr std::size_t value = detail::type_list_index_helper<0, Target, Types...>::value;
 | 
						|
    };
 | 
						|
 | 
						|
    template<std::size_t Index, class... Types >
 | 
						|
    struct type_list_element
 | 
						|
    {
 | 
						|
        using type = typename std::tuple_element<Index, std::tuple<Types...> >::type;
 | 
						|
    };
 | 
						|
 | 
						|
    class bad_variant_access: public std::exception
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        virtual const char *what() const noexcept override
 | 
						|
        {
 | 
						|
            return "Bad variant access";
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    // Interface ///////////////////////////////////////////////////////////////
 | 
						|
    struct monostate {};
 | 
						|
    inline bool operator==(const util::monostate&, const util::monostate&)
 | 
						|
    {
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts> // FIXME: no references, arrays, and void
 | 
						|
    class variant
 | 
						|
    {
 | 
						|
        // FIXME: Replace with std::aligned_union after gcc4.8 support is dropped
 | 
						|
        static constexpr const std::size_t S = cv::detail::max_of_t<sizeof(Ts)...>::value;
 | 
						|
        static constexpr const std::size_t A = cv::detail::max_of_t<alignof(Ts)...>::value;
 | 
						|
        using Memory = typename std::aligned_storage<S, A>::type[1];
 | 
						|
 | 
						|
        template<typename T> struct cctr_h {
 | 
						|
            static void help(Memory memory, const Memory from) {
 | 
						|
                new (memory) T(*reinterpret_cast<const T*>(from));
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T> struct mctr_h {
 | 
						|
            static void help(Memory memory, void *pval) {
 | 
						|
                new (memory) T(std::move(*reinterpret_cast<T*>(pval)));
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        //FIXME: unify with cctr_h and mctr_h
 | 
						|
        template<typename T> struct cnvrt_ctor_h {
 | 
						|
            static void help(Memory memory, void* from) {
 | 
						|
                using util::decay_t;
 | 
						|
                new (memory) decay_t<T>(std::forward<T>(*reinterpret_cast<decay_t<T>*>(from)));
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T> struct copy_h {
 | 
						|
            static void help(Memory to, const Memory from) {
 | 
						|
                *reinterpret_cast<T*>(to) = *reinterpret_cast<const T*>(from);
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T> struct move_h {
 | 
						|
            static void help(Memory to, Memory from) {
 | 
						|
                *reinterpret_cast<T*>(to) = std::move(*reinterpret_cast<T*>(from));
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        //FIXME: unify with copy_h and move_h
 | 
						|
        template<typename T> struct cnvrt_assign_h {
 | 
						|
            static void help(Memory to, void* from) {
 | 
						|
                using util::decay_t;
 | 
						|
                *reinterpret_cast<decay_t<T>*>(to) = std::forward<T>(*reinterpret_cast<decay_t<T>*>(from));
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T> struct swap_h {
 | 
						|
            static void help(Memory to, Memory from) {
 | 
						|
                std::swap(*reinterpret_cast<T*>(to), *reinterpret_cast<T*>(from));
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T> struct dtor_h {
 | 
						|
            static void help(Memory memory) {
 | 
						|
                (void) memory; // MSCV warning
 | 
						|
                reinterpret_cast<T*>(memory)->~T();
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T> struct equal_h {
 | 
						|
            static bool help(const Memory lhs, const Memory rhs) {
 | 
						|
                const T& t_lhs = *reinterpret_cast<const T*>(lhs);
 | 
						|
                const T& t_rhs = *reinterpret_cast<const T*>(rhs);
 | 
						|
                return t_lhs == t_rhs;
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        typedef void (*CCtr) (Memory, const Memory);  // Copy c-tor (variant)
 | 
						|
        typedef void (*MCtr) (Memory, void*);         // Generic move c-tor
 | 
						|
        typedef void (*Copy) (Memory, const Memory);  // Copy assignment
 | 
						|
        typedef void (*Move) (Memory, Memory);        // Move assignment
 | 
						|
 | 
						|
        typedef void (*Swap) (Memory, Memory);        // Swap
 | 
						|
        typedef void (*Dtor) (Memory);                // Destructor
 | 
						|
 | 
						|
        using  cnvrt_assgn_t   = void (*) (Memory, void*);  // Converting assignment (via std::forward)
 | 
						|
        using  cnvrt_ctor_t    = void (*) (Memory, void*);  // Converting constructor (via std::forward)
 | 
						|
 | 
						|
        typedef bool (*Equal)(const Memory, const Memory); // Equality test (external)
 | 
						|
 | 
						|
        static constexpr std::array<CCtr, sizeof...(Ts)> cctrs(){ return {{(&cctr_h<Ts>::help)...}};}
 | 
						|
        static constexpr std::array<MCtr, sizeof...(Ts)> mctrs(){ return {{(&mctr_h<Ts>::help)...}};}
 | 
						|
        static constexpr std::array<Copy, sizeof...(Ts)> cpyrs(){ return {{(©_h<Ts>::help)...}};}
 | 
						|
        static constexpr std::array<Move, sizeof...(Ts)> mvers(){ return {{(&move_h<Ts>::help)...}};}
 | 
						|
        static constexpr std::array<Swap, sizeof...(Ts)> swprs(){ return {{(&swap_h<Ts>::help)...}};}
 | 
						|
        static constexpr std::array<Dtor, sizeof...(Ts)> dtors(){ return {{(&dtor_h<Ts>::help)...}};}
 | 
						|
 | 
						|
        template<bool cond, typename T>
 | 
						|
        struct conditional_ref : std::conditional<cond, typename std::remove_reference<T>::type&, typename std::remove_reference<T>::type > {};
 | 
						|
 | 
						|
        template<bool cond, typename T>
 | 
						|
        using conditional_ref_t = typename conditional_ref<cond, T>::type;
 | 
						|
 | 
						|
 | 
						|
        template<bool is_lvalue_arg>
 | 
						|
        static constexpr std::array<cnvrt_assgn_t, sizeof...(Ts)> cnvrt_assgnrs(){
 | 
						|
            return {{(&cnvrt_assign_h<conditional_ref_t<is_lvalue_arg,Ts>>::help)...}};
 | 
						|
        }
 | 
						|
 | 
						|
        template<bool is_lvalue_arg>
 | 
						|
        static constexpr std::array<cnvrt_ctor_t, sizeof...(Ts)> cnvrt_ctors(){
 | 
						|
            return {{(&cnvrt_ctor_h<conditional_ref_t<is_lvalue_arg,Ts>>::help)...}};
 | 
						|
        }
 | 
						|
 | 
						|
        std::size_t m_index = 0;
 | 
						|
 | 
						|
    protected:
 | 
						|
        template<typename T, typename... Us> friend T& get(variant<Us...> &v);
 | 
						|
        template<typename T, typename... Us> friend const T& get(const variant<Us...> &v);
 | 
						|
        template<typename T, typename... Us> friend T* get_if(variant<Us...> *v) noexcept;
 | 
						|
        template<typename T, typename... Us> friend const T* get_if(const variant<Us...> *v) noexcept;
 | 
						|
 | 
						|
        template<typename... Us> friend bool operator==(const variant<Us...> &lhs,
 | 
						|
                                                        const variant<Us...> &rhs);
 | 
						|
        Memory memory;
 | 
						|
 | 
						|
    public:
 | 
						|
        // Constructors
 | 
						|
        variant() noexcept;
 | 
						|
        variant(const variant& other);
 | 
						|
        variant(variant&& other) noexcept;
 | 
						|
        // are_different_t is a SFINAE trick to avoid variant(T &&t) with T=variant
 | 
						|
        // for some reason, this version is called instead of variant(variant&& o) when
 | 
						|
        // variant is used in STL containers (examples: vector assignment).
 | 
						|
        template<
 | 
						|
            typename T,
 | 
						|
            typename = util::are_different_t<variant, T>
 | 
						|
        >
 | 
						|
        explicit variant(T&& t);
 | 
						|
        // template<class T, class... Args> explicit variant(Args&&... args);
 | 
						|
        // FIXME: other constructors
 | 
						|
 | 
						|
        // Destructor
 | 
						|
        ~variant();
 | 
						|
 | 
						|
        // Assignment
 | 
						|
        variant& operator=(const variant& rhs);
 | 
						|
        variant& operator=(variant &&rhs) noexcept;
 | 
						|
 | 
						|
        // SFINAE trick to avoid operator=(T&&) with T=variant<>, see comment above
 | 
						|
        template<
 | 
						|
            typename T,
 | 
						|
            typename = util::are_different_t<variant, T>
 | 
						|
        >
 | 
						|
        variant& operator=(T&& t) noexcept;
 | 
						|
 | 
						|
        // Observers
 | 
						|
        std::size_t index() const noexcept;
 | 
						|
        // FIXME: valueless_by_exception()
 | 
						|
 | 
						|
        // Modifiers
 | 
						|
        // FIXME: emplace()
 | 
						|
        void swap(variant &rhs) noexcept;
 | 
						|
 | 
						|
        // Non-C++17x!
 | 
						|
        template<typename T> static constexpr std::size_t index_of();
 | 
						|
    };
 | 
						|
 | 
						|
    // FIMXE: visit
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    T* get_if(util::variant<Types...>* v) noexcept;
 | 
						|
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    const T* get_if(const util::variant<Types...>* v) noexcept;
 | 
						|
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    T& get(util::variant<Types...> &v);
 | 
						|
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    const T& get(const util::variant<Types...> &v);
 | 
						|
 | 
						|
    template<std::size_t Index, typename... Types>
 | 
						|
    typename util::type_list_element<Index, Types...>::type& get(util::variant<Types...> &v);
 | 
						|
 | 
						|
    template<std::size_t Index, typename... Types>
 | 
						|
    const typename util::type_list_element<Index, Types...>::type& get(const util::variant<Types...> &v);
 | 
						|
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    bool holds_alternative(const util::variant<Types...> &v) noexcept;
 | 
						|
 | 
						|
 | 
						|
    // Visitor
 | 
						|
    namespace detail
 | 
						|
    {
 | 
						|
        struct visitor_interface {};
 | 
						|
 | 
						|
        // Class `visitor_return_type_deduction_helper`
 | 
						|
        // introduces solution for deduction `return_type` in `visit` function in common way
 | 
						|
        // for both Lambda and class Visitor and keep one interface invocation point: `visit` only
 | 
						|
        // his helper class is required to unify return_type deduction mechanism because
 | 
						|
        // for Lambda it is possible to take type of `decltype(visitor(get<0>(var)))`
 | 
						|
        // but for class Visitor there is no operator() in base case,
 | 
						|
        // because it provides `operator() (std::size_t index, ...)`
 | 
						|
        // So `visitor_return_type_deduction_helper` expose `operator()`
 | 
						|
        // uses only for class Visitor only for deduction `return type` in visit()
 | 
						|
        template<typename R>
 | 
						|
        struct visitor_return_type_deduction_helper
 | 
						|
        {
 | 
						|
            using return_type = R;
 | 
						|
 | 
						|
            // to be used in Lambda return type deduction context only
 | 
						|
            template<typename T>
 | 
						|
            return_type operator() (T&&);
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    // Special purpose `static_visitor` can receive additional arguments
 | 
						|
    template<typename R, typename Impl>
 | 
						|
    struct static_visitor : public detail::visitor_interface,
 | 
						|
                            public detail::visitor_return_type_deduction_helper<R> {
 | 
						|
 | 
						|
        // assign responsibility for return type deduction to helper class
 | 
						|
        using return_type = typename detail::visitor_return_type_deduction_helper<R>::return_type;
 | 
						|
        using detail::visitor_return_type_deduction_helper<R>::operator();
 | 
						|
        friend Impl;
 | 
						|
 | 
						|
        template<typename VariantValue, typename ...Args>
 | 
						|
        return_type operator() (std::size_t index, VariantValue&& value, Args&& ...args)
 | 
						|
        {
 | 
						|
            suppress_unused_warning(index);
 | 
						|
            return static_cast<Impl*>(this)-> visit(
 | 
						|
                                                std::forward<VariantValue>(value),
 | 
						|
                                                std::forward<Args>(args)...);
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    // Special purpose `static_indexed_visitor` can receive additional arguments
 | 
						|
    // And make forwarding current variant index as runtime function argument to its `Impl`
 | 
						|
    template<typename R, typename Impl>
 | 
						|
    struct static_indexed_visitor : public detail::visitor_interface,
 | 
						|
                                    public detail::visitor_return_type_deduction_helper<R> {
 | 
						|
 | 
						|
        // assign responsibility for return type deduction to helper class
 | 
						|
        using return_type = typename detail::visitor_return_type_deduction_helper<R>::return_type;
 | 
						|
        using detail::visitor_return_type_deduction_helper<R>::operator();
 | 
						|
        friend Impl;
 | 
						|
 | 
						|
        template<typename VariantValue, typename ...Args>
 | 
						|
        return_type operator() (std::size_t Index, VariantValue&& value, Args&& ...args)
 | 
						|
        {
 | 
						|
            return static_cast<Impl*>(this)-> visit(Index,
 | 
						|
                                                std::forward<VariantValue>(value),
 | 
						|
                                                std::forward<Args>(args)...);
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    template <class T>
 | 
						|
    struct variant_size;
 | 
						|
 | 
						|
    template <class... Types>
 | 
						|
    struct variant_size<util::variant<Types...>>
 | 
						|
        : std::integral_constant<std::size_t, sizeof...(Types)> { };
 | 
						|
    // FIXME: T&&, const TT&& versions.
 | 
						|
 | 
						|
    // Implementation //////////////////////////////////////////////////////////
 | 
						|
    template<typename... Ts>
 | 
						|
    variant<Ts...>::variant() noexcept
 | 
						|
    {
 | 
						|
        typedef typename std::tuple_element<0, std::tuple<Ts...> >::type TFirst;
 | 
						|
        new (memory) TFirst();
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    variant<Ts...>::variant(const variant &other)
 | 
						|
        : m_index(other.m_index)
 | 
						|
    {
 | 
						|
        (cctrs()[m_index])(memory, other.memory);
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    variant<Ts...>::variant(variant &&other) noexcept
 | 
						|
        : m_index(other.m_index)
 | 
						|
    {
 | 
						|
        (mctrs()[m_index])(memory, other.memory);
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    template<class T, typename>
 | 
						|
    variant<Ts...>::variant(T&& t)
 | 
						|
        : m_index(util::type_list_index<util::decay_t<T>, Ts...>::value)
 | 
						|
    {
 | 
						|
        const constexpr bool is_lvalue_arg =  std::is_lvalue_reference<T>::value;
 | 
						|
        (cnvrt_ctors<is_lvalue_arg>()[m_index])(memory, const_cast<util::decay_t<T> *>(&t));
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    variant<Ts...>::~variant()
 | 
						|
    {
 | 
						|
        (dtors()[m_index])(memory);
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    variant<Ts...>& variant<Ts...>::operator=(const variant<Ts...> &rhs)
 | 
						|
    {
 | 
						|
        if (m_index != rhs.m_index)
 | 
						|
        {
 | 
						|
            (dtors()[    m_index])(memory);
 | 
						|
            (cctrs()[rhs.m_index])(memory, rhs.memory);
 | 
						|
            m_index = rhs.m_index;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            (cpyrs()[rhs.m_index])(memory, rhs.memory);
 | 
						|
        }
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    variant<Ts...>& variant<Ts...>::operator=(variant<Ts...> &&rhs) noexcept
 | 
						|
    {
 | 
						|
        if (m_index != rhs.m_index)
 | 
						|
        {
 | 
						|
            (dtors()[    m_index])(memory);
 | 
						|
            (mctrs()[rhs.m_index])(memory, rhs.memory);
 | 
						|
            m_index = rhs.m_index;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            (mvers()[rhs.m_index])(memory, rhs.memory);
 | 
						|
        }
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    template<typename T, typename>
 | 
						|
    variant<Ts...>& variant<Ts...>::operator=(T&& t) noexcept
 | 
						|
    {
 | 
						|
        using decayed_t = util::decay_t<T>;
 | 
						|
        // FIXME: No version with implicit type conversion available!
 | 
						|
        const constexpr std::size_t t_index =
 | 
						|
            util::type_list_index<decayed_t, Ts...>::value;
 | 
						|
 | 
						|
        const constexpr bool is_lvalue_arg =  std::is_lvalue_reference<T>::value;
 | 
						|
 | 
						|
        if (t_index != m_index)
 | 
						|
        {
 | 
						|
            (dtors()[m_index])(memory);
 | 
						|
            (cnvrt_ctors<is_lvalue_arg>()[t_index])(memory, &t);
 | 
						|
            m_index = t_index;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            (cnvrt_assgnrs<is_lvalue_arg>()[m_index])(memory, &t);
 | 
						|
        }
 | 
						|
        return *this;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    std::size_t util::variant<Ts...>::index() const noexcept
 | 
						|
    {
 | 
						|
        return m_index;
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    void variant<Ts...>::swap(variant<Ts...> &rhs) noexcept
 | 
						|
    {
 | 
						|
        if (m_index == rhs.index())
 | 
						|
        {
 | 
						|
            (swprs()[m_index](memory, rhs.memory));
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            variant<Ts...> tmp(std::move(*this));
 | 
						|
            *this = std::move(rhs);
 | 
						|
            rhs   = std::move(tmp);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Ts>
 | 
						|
    template<typename T>
 | 
						|
    constexpr std::size_t variant<Ts...>::index_of()
 | 
						|
    {
 | 
						|
        return util::type_list_index<T, Ts...>::value; // FIXME: tests!
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    T* get_if(util::variant<Types...>* v) noexcept
 | 
						|
    {
 | 
						|
        const constexpr std::size_t t_index =
 | 
						|
            util::type_list_index<T, Types...>::value;
 | 
						|
 | 
						|
        if (v && v->index() == t_index)
 | 
						|
            return (T*)(&v->memory);  // workaround for ICC 2019
 | 
						|
            // original code: return reinterpret_cast<T&>(v.memory);
 | 
						|
        return nullptr;
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    const T* get_if(const util::variant<Types...>* v) noexcept
 | 
						|
    {
 | 
						|
        const constexpr std::size_t t_index =
 | 
						|
            util::type_list_index<T, Types...>::value;
 | 
						|
 | 
						|
        if (v && v->index() == t_index)
 | 
						|
            return (const T*)(&v->memory);  // workaround for ICC 2019
 | 
						|
            // original code: return reinterpret_cast<const T&>(v.memory);
 | 
						|
        return nullptr;
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    T& get(util::variant<Types...> &v)
 | 
						|
    {
 | 
						|
        if (auto* p = get_if<T>(&v))
 | 
						|
            return *p;
 | 
						|
        else
 | 
						|
            throw_error(bad_variant_access());
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    const T& get(const util::variant<Types...> &v)
 | 
						|
    {
 | 
						|
        if (auto* p = get_if<T>(&v))
 | 
						|
            return *p;
 | 
						|
        else
 | 
						|
            throw_error(bad_variant_access());
 | 
						|
    }
 | 
						|
 | 
						|
    template<std::size_t Index, typename... Types>
 | 
						|
    typename util::type_list_element<Index, Types...>::type& get(util::variant<Types...> &v)
 | 
						|
    {
 | 
						|
        using ReturnType = typename util::type_list_element<Index, Types...>::type;
 | 
						|
        return const_cast<ReturnType&>(get<Index, Types...>(static_cast<const util::variant<Types...> &>(v)));
 | 
						|
    }
 | 
						|
 | 
						|
    template<std::size_t Index, typename... Types>
 | 
						|
    const typename util::type_list_element<Index, Types...>::type& get(const util::variant<Types...> &v)
 | 
						|
    {
 | 
						|
        static_assert(Index < sizeof...(Types),
 | 
						|
                      "`Index` it out of bound of `util::variant` type list");
 | 
						|
        using ReturnType = typename util::type_list_element<Index, Types...>::type;
 | 
						|
        return get<ReturnType>(v);
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T, typename... Types>
 | 
						|
    bool holds_alternative(const util::variant<Types...> &v) noexcept
 | 
						|
    {
 | 
						|
        return v.index() == util::variant<Types...>::template index_of<T>();
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Us> bool operator==(const variant<Us...> &lhs,
 | 
						|
                                             const variant<Us...> &rhs)
 | 
						|
    {
 | 
						|
        using V = variant<Us...>;
 | 
						|
 | 
						|
        // Instantiate table only here since it requires operator== for <Us...>
 | 
						|
        // <Us...> should have operator== only if this one is used, not in general
 | 
						|
        static const std::array<typename V::Equal, sizeof...(Us)> eqs = {
 | 
						|
            {(&V::template equal_h<Us>::help)...}
 | 
						|
        };
 | 
						|
        if (lhs.index() != rhs.index())
 | 
						|
            return false;
 | 
						|
        return (eqs[lhs.index()])(lhs.memory, rhs.memory);
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename... Us> bool operator!=(const variant<Us...> &lhs,
 | 
						|
                                             const variant<Us...> &rhs)
 | 
						|
    {
 | 
						|
        return !(lhs == rhs);
 | 
						|
    }
 | 
						|
 | 
						|
namespace detail
 | 
						|
{
 | 
						|
    // terminate recursion implementation for `non-void` ReturnType
 | 
						|
    template<typename ReturnType, std::size_t CurIndex, std::size_t ElemCount,
 | 
						|
             typename Visitor, typename Variant, typename... VisitorArgs>
 | 
						|
    ReturnType apply_visitor_impl(Visitor&&, Variant&,
 | 
						|
                                  std::true_type, std::false_type,
 | 
						|
                                  VisitorArgs&& ...)
 | 
						|
    {
 | 
						|
        return {};
 | 
						|
    }
 | 
						|
 | 
						|
    // terminate recursion implementation for `void` ReturnType
 | 
						|
    template<typename ReturnType, std::size_t CurIndex, std::size_t ElemCount,
 | 
						|
             typename Visitor, typename Variant, typename... VisitorArgs>
 | 
						|
    void apply_visitor_impl(Visitor&&, Variant&,
 | 
						|
                            std::true_type, std::true_type,
 | 
						|
                            VisitorArgs&& ...)
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    // Intermediate resursion processor for Lambda Visitors
 | 
						|
    template<typename ReturnType, std::size_t CurIndex, std::size_t ElemCount,
 | 
						|
             typename Visitor, typename Variant, bool no_return_value, typename... VisitorArgs>
 | 
						|
    typename std::enable_if<!std::is_base_of<visitor_interface, typename std::decay<Visitor>::type>::value, ReturnType>::type
 | 
						|
         apply_visitor_impl(Visitor&& visitor, Variant&& v, std::false_type not_processed,
 | 
						|
                                               std::integral_constant<bool, no_return_value> should_no_return,
 | 
						|
                                               VisitorArgs&& ...args)
 | 
						|
    {
 | 
						|
        static_assert(std::is_same<ReturnType, decltype(visitor(get<CurIndex>(v)))>::value,
 | 
						|
                      "Different `ReturnType`s detected! All `Visitor::visit` or `overload_lamba_set`"
 | 
						|
                      " must return the same type");
 | 
						|
        suppress_unused_warning(not_processed);
 | 
						|
        if (v.index() == CurIndex)
 | 
						|
        {
 | 
						|
            return visitor.operator()(get<CurIndex>(v), std::forward<VisitorArgs>(args)... );
 | 
						|
        }
 | 
						|
 | 
						|
        using is_variant_processed_t = std::integral_constant<bool, CurIndex + 1 >= ElemCount>;
 | 
						|
        return apply_visitor_impl<ReturnType, CurIndex +1, ElemCount>(
 | 
						|
                                  std::forward<Visitor>(visitor),
 | 
						|
                                  std::forward<Variant>(v),
 | 
						|
                                  is_variant_processed_t{},
 | 
						|
                                  should_no_return,
 | 
						|
                                  std::forward<VisitorArgs>(args)...);
 | 
						|
    }
 | 
						|
 | 
						|
    //Visual Studio 2014 compilation fix: cast visitor to base class before invoke operator()
 | 
						|
    template<std::size_t CurIndex, typename ReturnType, typename Visitor, class Value, typename... VisitorArgs>
 | 
						|
    typename std::enable_if<std::is_base_of<static_visitor<ReturnType, typename std::decay<Visitor>::type>,
 | 
						|
                                            typename std::decay<Visitor>::type>::value, ReturnType>::type
 | 
						|
    invoke_class_visitor(Visitor& visitor, Value&& v,  VisitorArgs&&...args)
 | 
						|
    {
 | 
						|
        return static_cast<static_visitor<ReturnType, typename std::decay<Visitor>::type>&>(visitor).operator() (CurIndex, std::forward<Value>(v), std::forward<VisitorArgs>(args)... );
 | 
						|
    }
 | 
						|
 | 
						|
    //Visual Studio 2014 compilation fix: cast visitor to base class before invoke operator()
 | 
						|
    template<std::size_t CurIndex, typename ReturnType, typename Visitor, class Value, typename... VisitorArgs>
 | 
						|
    typename std::enable_if<std::is_base_of<static_indexed_visitor<ReturnType, typename std::decay<Visitor>::type>,
 | 
						|
                                            typename std::decay<Visitor>::type>::value, ReturnType>::type
 | 
						|
    invoke_class_visitor(Visitor& visitor, Value&& v,  VisitorArgs&&...args)
 | 
						|
    {
 | 
						|
        return static_cast<static_indexed_visitor<ReturnType, typename std::decay<Visitor>::type>&>(visitor).operator() (CurIndex, std::forward<Value>(v), std::forward<VisitorArgs>(args)... );
 | 
						|
    }
 | 
						|
 | 
						|
    // Intermediate recursion processor for special case `visitor_interface` derived Visitors
 | 
						|
    template<typename ReturnType, std::size_t CurIndex, std::size_t ElemCount,
 | 
						|
             typename Visitor, typename Variant, bool no_return_value, typename... VisitorArgs>
 | 
						|
    typename std::enable_if<std::is_base_of<visitor_interface, typename std::decay<Visitor>::type>::value, ReturnType>::type
 | 
						|
         apply_visitor_impl(Visitor&& visitor, Variant&& v, std::false_type not_processed,
 | 
						|
                                               std::integral_constant<bool, no_return_value> should_no_return,
 | 
						|
                                               VisitorArgs&& ...args)
 | 
						|
    {
 | 
						|
        static_assert(std::is_same<ReturnType, decltype(visitor(get<CurIndex>(v)))>::value,
 | 
						|
                      "Different `ReturnType`s detected! All `Visitor::visit` or `overload_lamba_set`"
 | 
						|
                      " must return the same type");
 | 
						|
        suppress_unused_warning(not_processed);
 | 
						|
        if (v.index() == CurIndex)
 | 
						|
        {
 | 
						|
            return invoke_class_visitor<CurIndex, ReturnType>(visitor, get<CurIndex>(v), std::forward<VisitorArgs>(args)... );
 | 
						|
        }
 | 
						|
 | 
						|
        using is_variant_processed_t = std::integral_constant<bool, CurIndex + 1 >= ElemCount>;
 | 
						|
        return apply_visitor_impl<ReturnType, CurIndex +1, ElemCount>(
 | 
						|
                                  std::forward<Visitor>(visitor),
 | 
						|
                                  std::forward<Variant>(v),
 | 
						|
                                  is_variant_processed_t{},
 | 
						|
                                  should_no_return,
 | 
						|
                                  std::forward<VisitorArgs>(args)...);
 | 
						|
    }
 | 
						|
} // namespace detail
 | 
						|
 | 
						|
    template<typename Visitor, typename Variant, typename... VisitorArg>
 | 
						|
    auto visit(Visitor &visitor, const Variant& var, VisitorArg &&...args) -> decltype(visitor(get<0>(var)))
 | 
						|
    {
 | 
						|
        constexpr std::size_t varsize = util::variant_size<Variant>::value;
 | 
						|
        static_assert(varsize != 0, "utils::variant must contains one type at least ");
 | 
						|
        using is_variant_processed_t = std::false_type;
 | 
						|
 | 
						|
        using ReturnType = decltype(visitor(get<0>(var)));
 | 
						|
        using return_t = std::is_same<ReturnType, void>;
 | 
						|
        return detail::apply_visitor_impl<ReturnType, 0, varsize, Visitor>(
 | 
						|
                                    std::forward<Visitor>(visitor),
 | 
						|
                                    var, is_variant_processed_t{},
 | 
						|
                                    return_t{},
 | 
						|
                                    std::forward<VisitorArg>(args)...);
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename Visitor, typename Variant>
 | 
						|
    auto visit(Visitor&& visitor, const Variant& var) -> decltype(visitor(get<0>(var)))
 | 
						|
    {
 | 
						|
        constexpr std::size_t varsize = util::variant_size<Variant>::value;
 | 
						|
        static_assert(varsize != 0, "utils::variant must contains one type at least ");
 | 
						|
        using is_variant_processed_t = std::false_type;
 | 
						|
 | 
						|
        using ReturnType = decltype(visitor(get<0>(var)));
 | 
						|
        using return_t = std::is_same<ReturnType, void>;
 | 
						|
        return detail::apply_visitor_impl<ReturnType, 0, varsize, Visitor>(
 | 
						|
                                    std::forward<Visitor>(visitor),
 | 
						|
                                    var, is_variant_processed_t{},
 | 
						|
                                    return_t{});
 | 
						|
    }
 | 
						|
} // namespace util
 | 
						|
} // namespace cv
 | 
						|
 | 
						|
#endif // OPENCV_GAPI_UTIL_VARIANT_HPP
 |