github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/opencv4/include/opencv2/gapi/util/variant.hpp (about)

     1  // This file is part of OpenCV project.
     2  // It is subject to the license terms in the LICENSE file found in the top-level directory
     3  // of this distribution and at http://opencv.org/license.html.
     4  //
     5  // Copyright (C) 2018 Intel Corporation
     6  
     7  
     8  #ifndef OPENCV_GAPI_UTIL_VARIANT_HPP
     9  #define OPENCV_GAPI_UTIL_VARIANT_HPP
    10  
    11  #include <array>
    12  #include <type_traits>
    13  
    14  #include <opencv2/gapi/util/throw.hpp>
    15  #include <opencv2/gapi/util/util.hpp> // max_of_t
    16  #include <opencv2/gapi/util/type_traits.hpp>
    17  
    18  // A poor man's `variant` implementation, incompletely modeled against C++17 spec.
    19  namespace cv
    20  {
    21  namespace util
    22  {
    23      namespace detail
    24      {
    25          template<std::size_t I, typename Target, typename First, typename... Remaining>
    26          struct type_list_index_helper
    27          {
    28              static const constexpr bool is_same = std::is_same<Target, First>::value;
    29              static const constexpr std::size_t value =
    30                  std::conditional<is_same, std::integral_constant<std::size_t, I>, type_list_index_helper<I + 1, Target, Remaining...>>::type::value;
    31          };
    32  
    33          template<std::size_t I, typename Target, typename First>
    34          struct type_list_index_helper<I, Target, First>
    35          {
    36              static_assert(std::is_same<Target, First>::value, "Type not found");
    37              static const constexpr std::size_t value = I;
    38          };
    39      }
    40  
    41      template<typename Target, typename... Types>
    42      struct type_list_index
    43      {
    44          static const constexpr std::size_t value = detail::type_list_index_helper<0, Target, Types...>::value;
    45      };
    46  
    47      class bad_variant_access: public std::exception
    48      {
    49      public:
    50          virtual const char *what() const noexcept override
    51          {
    52              return "Bad variant access";
    53          }
    54      };
    55  
    56      // Interface ///////////////////////////////////////////////////////////////
    57      struct monostate {};
    58      inline bool operator==(const util::monostate&, const util::monostate&)
    59      {
    60          return true;
    61      }
    62  
    63      template<typename... Ts> // FIXME: no references, arrays, and void
    64      class variant
    65      {
    66          // FIXME: Replace with std::aligned_union after gcc4.8 support is dropped
    67          static constexpr const std::size_t S = cv::detail::max_of_t<sizeof(Ts)...>::value;
    68          static constexpr const std::size_t A = cv::detail::max_of_t<alignof(Ts)...>::value;
    69          using Memory = typename std::aligned_storage<S, A>::type[1];
    70  
    71          template<typename T> struct cctr_h {
    72              static void help(Memory memory, const Memory from) {
    73                  new (memory) T(*reinterpret_cast<const T*>(from));
    74              }
    75          };
    76  
    77          template<typename T> struct mctr_h {
    78              static void help(Memory memory, void *pval) {
    79                  new (memory) T(std::move(*reinterpret_cast<T*>(pval)));
    80              }
    81          };
    82  
    83          //FIXME: unify with cctr_h and mctr_h
    84          template<typename T> struct cnvrt_ctor_h {
    85              static void help(Memory memory, void* from) {
    86                  using util::decay_t;
    87                  new (memory) decay_t<T>(std::forward<T>(*reinterpret_cast<decay_t<T>*>(from)));
    88              }
    89          };
    90  
    91          template<typename T> struct copy_h {
    92              static void help(Memory to, const Memory from) {
    93                  *reinterpret_cast<T*>(to) = *reinterpret_cast<const T*>(from);
    94              }
    95          };
    96  
    97          template<typename T> struct move_h {
    98              static void help(Memory to, Memory from) {
    99                  *reinterpret_cast<T*>(to) = std::move(*reinterpret_cast<T*>(from));
   100              }
   101          };
   102  
   103          //FIXME: unify with copy_h and move_h
   104          template<typename T> struct cnvrt_assign_h {
   105              static void help(Memory to, void* from) {
   106                  using util::decay_t;
   107                  *reinterpret_cast<decay_t<T>*>(to) = std::forward<T>(*reinterpret_cast<decay_t<T>*>(from));
   108              }
   109          };
   110  
   111          template<typename T> struct swap_h {
   112              static void help(Memory to, Memory from) {
   113                  std::swap(*reinterpret_cast<T*>(to), *reinterpret_cast<T*>(from));
   114              }
   115          };
   116  
   117          template<typename T> struct dtor_h {
   118              static void help(Memory memory) {
   119                  (void) memory; // MSCV warning
   120                  reinterpret_cast<T*>(memory)->~T();
   121              }
   122          };
   123  
   124          template<typename T> struct equal_h {
   125              static bool help(const Memory lhs, const Memory rhs) {
   126                  const T& t_lhs = *reinterpret_cast<const T*>(lhs);
   127                  const T& t_rhs = *reinterpret_cast<const T*>(rhs);
   128                  return t_lhs == t_rhs;
   129              }
   130          };
   131  
   132          typedef void (*CCtr) (Memory, const Memory);  // Copy c-tor (variant)
   133          typedef void (*MCtr) (Memory, void*);         // Generic move c-tor
   134          typedef void (*Copy) (Memory, const Memory);  // Copy assignment
   135          typedef void (*Move) (Memory, Memory);        // Move assignment
   136  
   137          typedef void (*Swap) (Memory, Memory);        // Swap
   138          typedef void (*Dtor) (Memory);                // Destructor
   139  
   140          using  cnvrt_assgn_t   = void (*) (Memory, void*);  // Converting assignment (via std::forward)
   141          using  cnvrt_ctor_t    = void (*) (Memory, void*);  // Converting constructor (via std::forward)
   142  
   143          typedef bool (*Equal)(const Memory, const Memory); // Equality test (external)
   144  
   145          static constexpr std::array<CCtr, sizeof...(Ts)> cctrs(){ return {{(&cctr_h<Ts>::help)...}};}
   146          static constexpr std::array<MCtr, sizeof...(Ts)> mctrs(){ return {{(&mctr_h<Ts>::help)...}};}
   147          static constexpr std::array<Copy, sizeof...(Ts)> cpyrs(){ return {{(&copy_h<Ts>::help)...}};}
   148          static constexpr std::array<Move, sizeof...(Ts)> mvers(){ return {{(&move_h<Ts>::help)...}};}
   149          static constexpr std::array<Swap, sizeof...(Ts)> swprs(){ return {{(&swap_h<Ts>::help)...}};}
   150          static constexpr std::array<Dtor, sizeof...(Ts)> dtors(){ return {{(&dtor_h<Ts>::help)...}};}
   151  
   152          template<bool cond, typename T>
   153          struct conditional_ref : std::conditional<cond, typename std::remove_reference<T>::type&, typename std::remove_reference<T>::type > {};
   154  
   155          template<bool cond, typename T>
   156          using conditional_ref_t = typename conditional_ref<cond, T>::type;
   157  
   158  
   159          template<bool is_lvalue_arg>
   160          static constexpr std::array<cnvrt_assgn_t, sizeof...(Ts)> cnvrt_assgnrs(){
   161              return {{(&cnvrt_assign_h<conditional_ref_t<is_lvalue_arg,Ts>>::help)...}};
   162          }
   163  
   164          template<bool is_lvalue_arg>
   165          static constexpr std::array<cnvrt_ctor_t, sizeof...(Ts)> cnvrt_ctors(){
   166              return {{(&cnvrt_ctor_h<conditional_ref_t<is_lvalue_arg,Ts>>::help)...}};
   167          }
   168  
   169          std::size_t m_index = 0;
   170  
   171      protected:
   172          template<typename T, typename... Us> friend T& get(variant<Us...> &v);
   173          template<typename T, typename... Us> friend const T& get(const variant<Us...> &v);
   174          template<typename T, typename... Us> friend T* get_if(variant<Us...> *v) noexcept;
   175          template<typename T, typename... Us> friend const T* get_if(const variant<Us...> *v) noexcept;
   176  
   177          template<typename... Us> friend bool operator==(const variant<Us...> &lhs,
   178                                                          const variant<Us...> &rhs);
   179          Memory memory;
   180  
   181      public:
   182          // Constructors
   183          variant() noexcept;
   184          variant(const variant& other);
   185          variant(variant&& other) noexcept;
   186          // are_different_t is a SFINAE trick to avoid variant(T &&t) with T=variant
   187          // for some reason, this version is called instead of variant(variant&& o) when
   188          // variant is used in STL containers (examples: vector assignment).
   189          template<
   190              typename T,
   191              typename = util::are_different_t<variant, T>
   192          >
   193          explicit variant(T&& t);
   194          // template<class T, class... Args> explicit variant(Args&&... args);
   195          // FIXME: other constructors
   196  
   197          // Destructor
   198          ~variant();
   199  
   200          // Assignment
   201          variant& operator=(const variant& rhs);
   202          variant& operator=(variant &&rhs) noexcept;
   203  
   204          // SFINAE trick to avoid operator=(T&&) with T=variant<>, see comment above
   205          template<
   206              typename T,
   207              typename = util::are_different_t<variant, T>
   208          >
   209          variant& operator=(T&& t) noexcept;
   210  
   211          // Observers
   212          std::size_t index() const noexcept;
   213          // FIXME: valueless_by_exception()
   214  
   215          // Modifiers
   216          // FIXME: emplace()
   217          void swap(variant &rhs) noexcept;
   218  
   219          // Non-C++17x!
   220          template<typename T> static constexpr std::size_t index_of();
   221      };
   222  
   223      // FIMXE: visit
   224      template<typename T, typename... Types>
   225      T* get_if(util::variant<Types...>* v) noexcept;
   226  
   227      template<typename T, typename... Types>
   228      const T* get_if(const util::variant<Types...>* v) noexcept;
   229  
   230      template<typename T, typename... Types>
   231      T& get(util::variant<Types...> &v);
   232  
   233      template<typename T, typename... Types>
   234      const T& get(const util::variant<Types...> &v);
   235  
   236      template<typename T, typename... Types>
   237      bool holds_alternative(const util::variant<Types...> &v) noexcept;
   238  
   239      // FIXME: T&&, const TT&& versions.
   240  
   241      // Implementation //////////////////////////////////////////////////////////
   242      template<typename... Ts>
   243      variant<Ts...>::variant() noexcept
   244      {
   245          typedef typename std::tuple_element<0, std::tuple<Ts...> >::type TFirst;
   246          new (memory) TFirst();
   247      }
   248  
   249      template<typename... Ts>
   250      variant<Ts...>::variant(const variant &other)
   251          : m_index(other.m_index)
   252      {
   253          (cctrs()[m_index])(memory, other.memory);
   254      }
   255  
   256      template<typename... Ts>
   257      variant<Ts...>::variant(variant &&other) noexcept
   258          : m_index(other.m_index)
   259      {
   260          (mctrs()[m_index])(memory, other.memory);
   261      }
   262  
   263      template<typename... Ts>
   264      template<class T, typename>
   265      variant<Ts...>::variant(T&& t)
   266          : m_index(util::type_list_index<util::decay_t<T>, Ts...>::value)
   267      {
   268          const constexpr bool is_lvalue_arg =  std::is_lvalue_reference<T>::value;
   269          (cnvrt_ctors<is_lvalue_arg>()[m_index])(memory, const_cast<util::decay_t<T> *>(&t));
   270      }
   271  
   272      template<typename... Ts>
   273      variant<Ts...>::~variant()
   274      {
   275          (dtors()[m_index])(memory);
   276      }
   277  
   278      template<typename... Ts>
   279      variant<Ts...>& variant<Ts...>::operator=(const variant<Ts...> &rhs)
   280      {
   281          if (m_index != rhs.m_index)
   282          {
   283              (dtors()[    m_index])(memory);
   284              (cctrs()[rhs.m_index])(memory, rhs.memory);
   285              m_index = rhs.m_index;
   286          }
   287          else
   288          {
   289              (cpyrs()[rhs.m_index])(memory, rhs.memory);
   290          }
   291          return *this;
   292      }
   293  
   294      template<typename... Ts>
   295      variant<Ts...>& variant<Ts...>::operator=(variant<Ts...> &&rhs) noexcept
   296      {
   297          if (m_index != rhs.m_index)
   298          {
   299              (dtors()[    m_index])(memory);
   300              (mctrs()[rhs.m_index])(memory, rhs.memory);
   301              m_index = rhs.m_index;
   302          }
   303          else
   304          {
   305              (mvers()[rhs.m_index])(memory, rhs.memory);
   306          }
   307          return *this;
   308      }
   309  
   310      template<typename... Ts>
   311      template<typename T, typename>
   312      variant<Ts...>& variant<Ts...>::operator=(T&& t) noexcept
   313      {
   314          using decayed_t = util::decay_t<T>;
   315          // FIXME: No version with implicit type conversion available!
   316          const constexpr std::size_t t_index =
   317              util::type_list_index<decayed_t, Ts...>::value;
   318  
   319          const constexpr bool is_lvalue_arg =  std::is_lvalue_reference<T>::value;
   320  
   321          if (t_index != m_index)
   322          {
   323              (dtors()[m_index])(memory);
   324              (cnvrt_ctors<is_lvalue_arg>()[t_index])(memory, &t);
   325              m_index = t_index;
   326          }
   327          else
   328          {
   329              (cnvrt_assgnrs<is_lvalue_arg>()[m_index])(memory, &t);
   330          }
   331          return *this;
   332  
   333      }
   334  
   335      template<typename... Ts>
   336      std::size_t util::variant<Ts...>::index() const noexcept
   337      {
   338          return m_index;
   339      }
   340  
   341      template<typename... Ts>
   342      void variant<Ts...>::swap(variant<Ts...> &rhs) noexcept
   343      {
   344          if (m_index == rhs.index())
   345          {
   346              (swprs()[m_index](memory, rhs.memory));
   347          }
   348          else
   349          {
   350              variant<Ts...> tmp(std::move(*this));
   351              *this = std::move(rhs);
   352              rhs   = std::move(tmp);
   353          }
   354      }
   355  
   356      template<typename... Ts>
   357      template<typename T>
   358      constexpr std::size_t variant<Ts...>::index_of()
   359      {
   360          return util::type_list_index<T, Ts...>::value; // FIXME: tests!
   361      }
   362  
   363      template<typename T, typename... Types>
   364      T* get_if(util::variant<Types...>* v) noexcept
   365      {
   366          const constexpr std::size_t t_index =
   367              util::type_list_index<T, Types...>::value;
   368  
   369          if (v && v->index() == t_index)
   370              return (T*)(&v->memory);  // workaround for ICC 2019
   371              // original code: return reinterpret_cast<T&>(v.memory);
   372          return nullptr;
   373      }
   374  
   375      template<typename T, typename... Types>
   376      const T* get_if(const util::variant<Types...>* v) noexcept
   377      {
   378          const constexpr std::size_t t_index =
   379              util::type_list_index<T, Types...>::value;
   380  
   381          if (v && v->index() == t_index)
   382              return (const T*)(&v->memory);  // workaround for ICC 2019
   383              // original code: return reinterpret_cast<const T&>(v.memory);
   384          return nullptr;
   385      }
   386  
   387      template<typename T, typename... Types>
   388      T& get(util::variant<Types...> &v)
   389      {
   390          if (auto* p = get_if<T>(&v))
   391              return *p;
   392          else
   393              throw_error(bad_variant_access());
   394      }
   395  
   396      template<typename T, typename... Types>
   397      const T& get(const util::variant<Types...> &v)
   398      {
   399          if (auto* p = get_if<T>(&v))
   400              return *p;
   401          else
   402              throw_error(bad_variant_access());
   403      }
   404  
   405      template<typename T, typename... Types>
   406      bool holds_alternative(const util::variant<Types...> &v) noexcept
   407      {
   408          return v.index() == util::variant<Types...>::template index_of<T>();
   409      }
   410  
   411      template<typename... Us> bool operator==(const variant<Us...> &lhs,
   412                                               const variant<Us...> &rhs)
   413      {
   414          using V = variant<Us...>;
   415  
   416          // Instantiate table only here since it requires operator== for <Us...>
   417          // <Us...> should have operator== only if this one is used, not in general
   418          static const std::array<typename V::Equal, sizeof...(Us)> eqs = {
   419              {(&V::template equal_h<Us>::help)...}
   420          };
   421          if (lhs.index() != rhs.index())
   422              return false;
   423          return (eqs[lhs.index()])(lhs.memory, rhs.memory);
   424      }
   425  
   426      template<typename... Us> bool operator!=(const variant<Us...> &lhs,
   427                                               const variant<Us...> &rhs)
   428      {
   429          return !(lhs == rhs);
   430      }
   431  } // namespace cv
   432  } // namespace util
   433  
   434  #endif // OPENCV_GAPI_UTIL_VARIANT_HPP