]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/variant2/variant.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / variant2 / variant.hpp
index d661ca5c53b6fe56865b23c0ab67190cc2a5b736..9c1fba9607af503dc0cc2738be189f55f971d4d7 100644 (file)
 #endif
 #include <boost/config.hpp>
 #include <boost/detail/workaround.hpp>
+#include <boost/cstdint.hpp>
 #include <cstddef>
 #include <type_traits>
 #include <exception>
 #include <cassert>
 #include <initializer_list>
 #include <utility>
+#include <functional> // std::hash
 
 //
 
@@ -1050,46 +1052,58 @@ template<class T> struct is_nothrow_swappable: mp11::mp_valid<det2::is_nothrow_s
 
 #endif
 
-} // namespace detail
+// variant_cc_base
 
-// variant
+template<bool CopyConstructible, bool TriviallyCopyConstructible, class... T> struct variant_cc_base_impl;
 
-template<class... T> class variant: private detail::variant_base<T...>
+template<class... T> using variant_cc_base = variant_cc_base_impl<
+    mp11::mp_all<std::is_copy_constructible<T>...>::value,
+    mp11::mp_all<detail::is_trivially_copy_constructible<T>...>::value,
+    T...>;
+
+template<class... T> struct variant_cc_base_impl<true, true, T...>: public variant_base<T...>
 {
-private:
+    using variant_base = detail::variant_base<T...>;
+    using variant_base::variant_base;
+
+    variant_cc_base_impl() = default;
+    variant_cc_base_impl( variant_cc_base_impl const& ) = default;
+    variant_cc_base_impl( variant_cc_base_impl && ) = default;
+    variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
+    variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
+};
 
+template<bool B, class... T> struct variant_cc_base_impl<false, B, T...>: public variant_base<T...>
+{
     using variant_base = detail::variant_base<T...>;
+    using variant_base::variant_base;
 
-private:
+    variant_cc_base_impl() = default;
+    variant_cc_base_impl( variant_cc_base_impl const& ) = delete;
+    variant_cc_base_impl( variant_cc_base_impl && ) = default;
+    variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
+    variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
+};
 
-    variant( variant const volatile& r ) = delete;
-    variant& operator=( variant const volatile& r ) = delete;
+template<class... T> struct variant_cc_base_impl<true, false, T...>: public variant_base<T...>
+{
+    using variant_base = detail::variant_base<T...>;
+    using variant_base::variant_base;
 
 public:
 
     // constructors
 
-    template<class E1 = void, class E2 = mp11::mp_if<std::is_default_constructible< mp11::mp_first<variant<T...>> >, E1>>
-    constexpr variant()
-        noexcept( std::is_nothrow_default_constructible< mp11::mp_first<variant<T...>> >::value )
-        : variant_base( mp11::mp_size_t<0>() )
-    {
-    }
+    variant_cc_base_impl() = default;
 
-    template<class E1 = void,
-        class E2 = mp11::mp_if<mp11::mp_all<detail::is_trivially_copy_constructible<T>...>, E1>
-    >
-    constexpr variant( variant const& r ) noexcept
-        : variant_base( static_cast<variant_base const&>(r) )
-    {
-    }
+    // copy constructor
 
 private:
 
     struct L1
     {
         variant_base * this_;
-        variant const & r;
+        variant_base const & r;
 
         template<class I> void operator()( I i ) const
         {
@@ -1099,30 +1113,151 @@ private:
 
 public:
 
-    template<class E1 = void,
-        class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<detail::is_trivially_copy_constructible<T>...>>, E1>,
-        class E3 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<T>...>, E1>
-    >
-    variant( variant const& r )
+    variant_cc_base_impl( variant_cc_base_impl const& r )
         noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
+        : variant_base()
     {
         mp11::mp_with_index<sizeof...(T)>( r.index(), L1{ this, r } );
     }
 
-    template<class E1 = void,
-        class E2 = mp11::mp_if<mp11::mp_all<detail::is_trivially_move_constructible<T>...>, E1>
-    >
-    constexpr variant( variant && r ) noexcept
-        : variant_base( static_cast<variant_base&&>(r) )
+    // move constructor
+
+    variant_cc_base_impl( variant_cc_base_impl && ) = default;
+
+    // assignment
+
+    variant_cc_base_impl& operator=( variant_cc_base_impl const & ) = default;
+    variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
+};
+
+// variant_ca_base
+
+template<bool CopyAssignable, bool TriviallyCopyAssignable, class... T> struct variant_ca_base_impl;
+
+template<class... T> using variant_ca_base = variant_ca_base_impl<
+    mp11::mp_all<std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>::value,
+    mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>::value,
+    T...>;
+
+template<class... T> struct variant_ca_base_impl<true, true, T...>: public variant_cc_base<T...>
+{
+    using variant_base = detail::variant_cc_base<T...>;
+    using variant_base::variant_base;
+
+    variant_ca_base_impl() = default;
+    variant_ca_base_impl( variant_ca_base_impl const& ) = default;
+    variant_ca_base_impl( variant_ca_base_impl && ) = default;
+    variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = default;
+    variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
+};
+
+template<bool B, class... T> struct variant_ca_base_impl<false, B, T...>: public variant_cc_base<T...>
+{
+    using variant_base = detail::variant_cc_base<T...>;
+    using variant_base::variant_base;
+
+    variant_ca_base_impl() = default;
+    variant_ca_base_impl( variant_ca_base_impl const& ) = default;
+    variant_ca_base_impl( variant_ca_base_impl && ) = default;
+    variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = delete;
+    variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
+};
+
+template<class... T> struct variant_ca_base_impl<true, false, T...>: public variant_cc_base<T...>
+{
+    using variant_base = detail::variant_cc_base<T...>;
+    using variant_base::variant_base;
+
+public:
+
+    // constructors
+
+    variant_ca_base_impl() = default;
+    variant_ca_base_impl( variant_ca_base_impl const& ) = default;
+    variant_ca_base_impl( variant_ca_base_impl && ) = default;
+
+    // copy assignment
+
+private:
+
+    struct L3
     {
+        variant_base * this_;
+        variant_base const & r;
+
+        template<class I> void operator()( I i ) const
+        {
+            this_->template emplace<I::value>( r._get_impl( i ) );
+        }
+    };
+
+public:
+
+    BOOST_CXX14_CONSTEXPR variant_ca_base_impl& operator=( variant_ca_base_impl const & r )
+        noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
+    {
+        mp11::mp_with_index<sizeof...(T)>( r.index(), L3{ this, r } );
+        return *this;
     }
 
+    // move assignment
+
+    variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
+};
+
+// variant_mc_base
+
+template<bool MoveConstructible, bool TriviallyMoveConstructible, class... T> struct variant_mc_base_impl;
+
+template<class... T> using variant_mc_base = variant_mc_base_impl<
+    mp11::mp_all<std::is_move_constructible<T>...>::value,
+    mp11::mp_all<detail::is_trivially_move_constructible<T>...>::value,
+    T...>;
+
+template<class... T> struct variant_mc_base_impl<true, true, T...>: public variant_ca_base<T...>
+{
+    using variant_base = detail::variant_ca_base<T...>;
+    using variant_base::variant_base;
+
+    variant_mc_base_impl() = default;
+    variant_mc_base_impl( variant_mc_base_impl const& ) = default;
+    variant_mc_base_impl( variant_mc_base_impl && ) = default;
+    variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
+    variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
+};
+
+template<bool B, class... T> struct variant_mc_base_impl<false, B, T...>: public variant_ca_base<T...>
+{
+    using variant_base = detail::variant_ca_base<T...>;
+    using variant_base::variant_base;
+
+    variant_mc_base_impl() = default;
+    variant_mc_base_impl( variant_mc_base_impl const& ) = default;
+    variant_mc_base_impl( variant_mc_base_impl && ) = delete;
+    variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
+    variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
+};
+
+template<class... T> struct variant_mc_base_impl<true, false, T...>: public variant_ca_base<T...>
+{
+    using variant_base = detail::variant_ca_base<T...>;
+    using variant_base::variant_base;
+
+public:
+
+    // constructors
+
+    variant_mc_base_impl() = default;
+    variant_mc_base_impl( variant_mc_base_impl const& ) = default;
+
+    // move constructor
+
 private:
 
     struct L2
     {
         variant_base * this_;
-        variant & r;
+        variant_base & r;
 
         template<class I> void operator()( I i ) const
         {
@@ -1132,16 +1267,117 @@ private:
 
 public:
 
-    template<class E1 = void,
-        class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<detail::is_trivially_move_constructible<T>...>>, E1>,
-        class E3 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<T>...>, E1>
-    >
-    variant( variant && r )
+    variant_mc_base_impl( variant_mc_base_impl && r )
         noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
     {
         mp11::mp_with_index<sizeof...(T)>( r.index(), L2{ this, r } );
     }
 
+    // assignment
+
+    variant_mc_base_impl& operator=( variant_mc_base_impl const & ) = default;
+    variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
+};
+
+// variant_ma_base
+
+template<bool MoveAssignable, bool TriviallyMoveAssignable, class... T> struct variant_ma_base_impl;
+
+template<class... T> using variant_ma_base = variant_ma_base_impl<
+    mp11::mp_all<std::is_move_constructible<T>..., std::is_move_assignable<T>...>::value,
+    mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>::value,
+    T...>;
+
+template<class... T> struct variant_ma_base_impl<true, true, T...>: public variant_mc_base<T...>
+{
+    using variant_base = detail::variant_mc_base<T...>;
+    using variant_base::variant_base;
+
+    variant_ma_base_impl() = default;
+    variant_ma_base_impl( variant_ma_base_impl const& ) = default;
+    variant_ma_base_impl( variant_ma_base_impl && ) = default;
+    variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
+    variant_ma_base_impl& operator=( variant_ma_base_impl && ) = default;
+};
+
+template<bool B, class... T> struct variant_ma_base_impl<false, B, T...>: public variant_mc_base<T...>
+{
+    using variant_base = detail::variant_mc_base<T...>;
+    using variant_base::variant_base;
+
+    variant_ma_base_impl() = default;
+    variant_ma_base_impl( variant_ma_base_impl const& ) = default;
+    variant_ma_base_impl( variant_ma_base_impl && ) = default;
+    variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
+    variant_ma_base_impl& operator=( variant_ma_base_impl && ) = delete;
+};
+
+template<class... T> struct variant_ma_base_impl<true, false, T...>: public variant_mc_base<T...>
+{
+    using variant_base = detail::variant_mc_base<T...>;
+    using variant_base::variant_base;
+
+public:
+
+    // constructors
+
+    variant_ma_base_impl() = default;
+    variant_ma_base_impl( variant_ma_base_impl const& ) = default;
+    variant_ma_base_impl( variant_ma_base_impl && ) = default;
+
+    // copy assignment
+
+    variant_ma_base_impl& operator=( variant_ma_base_impl const & ) = default;
+
+    // move assignment
+
+private:
+
+    struct L4
+    {
+        variant_base * this_;
+        variant_base & r;
+
+        template<class I> void operator()( I i ) const
+        {
+            this_->template emplace<I::value>( std::move( r._get_impl( i ) ) );
+        }
+    };
+
+public:
+
+    variant_ma_base_impl& operator=( variant_ma_base_impl && r )
+        noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
+    {
+        mp11::mp_with_index<sizeof...(T)>( r.index(), L4{ this, r } );
+        return *this;
+    }
+};
+
+} // namespace detail
+
+// variant
+
+template<class... T> class variant: private detail::variant_ma_base<T...>
+{
+private:
+
+    using variant_base = detail::variant_ma_base<T...>;
+
+public:
+
+    // constructors
+
+    template<class E1 = void, class E2 = mp11::mp_if<std::is_default_constructible< mp11::mp_first<variant<T...>> >, E1>>
+    constexpr variant()
+        noexcept( std::is_nothrow_default_constructible< mp11::mp_first<variant<T...>> >::value )
+        : variant_base( mp11::mp_size_t<0>() )
+    {
+    }
+
+    // variant( variant const& ) = default;
+    // variant( variant && ) = default;
+
     template<class U,
         class Ud = typename std::decay<U>::type,
         class E1 = typename std::enable_if< !std::is_same<Ud, variant>::value && !detail::is_in_place_index<Ud>::value && !detail::is_in_place_type<Ud>::value >::type,
@@ -1175,75 +1411,9 @@ public:
     }
 
     // assignment
-    template<class E1 = void,
-        class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>, E1>
-    >
-    BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r ) noexcept
-    {
-        static_cast<variant_base&>( *this ) = static_cast<variant_base const&>( r );
-        return *this;
-    }
-
-private:
-
-    struct L3
-    {
-        variant * this_;
-        variant const & r;
-
-        template<class I> void operator()( I i ) const
-        {
-            this_->variant_base::template emplace<I::value>( r._get_impl( i ) );
-        }
-    };
-
-public:
-
-    template<class E1 = void,
-        class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>>, E1>,
-        class E3 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>, E1>
-    >
-    BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r )
-        noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
-    {
-        mp11::mp_with_index<sizeof...(T)>( r.index(), L3{ this, r } );
-        return *this;
-    }
-
-    template<class E1 = void,
-        class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>, E1>
-    >
-    BOOST_CXX14_CONSTEXPR variant& operator=( variant && r ) noexcept
-    {
-        static_cast<variant_base&>( *this ) = static_cast<variant_base&&>( r );
-        return *this;
-    }
-
-private:
-
-    struct L4
-    {
-        variant * this_;
-        variant & r;
 
-        template<class I> void operator()( I i ) const
-        {
-            this_->variant_base::template emplace<I::value>( std::move( r._get_impl( i ) ) );
-        }
-    };
-
-public:
-
-    template<class E1 = void,
-        class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>>, E1>,
-        class E3 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<T>..., std::is_move_assignable<T>...>, E1>
-    >
-    variant& operator=( variant && r )
-        noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
-    {
-        mp11::mp_with_index<sizeof...(T)>( r.index(), L4{ this, r } );
-        return *this;
-    }
+    // variant& operator=( variant const& ) = default;
+    // variant& operator=( variant && ) = default;
 
     template<class U,
         class E1 = typename std::enable_if<!std::is_same<typename std::decay<U>::type, variant>::value>::type,
@@ -1785,9 +1955,92 @@ void swap( variant<T...> & v, variant<T...> & w )
     v.swap( w );
 }
 
+// hashing support
+
+namespace detail
+{
+
+template<class V> struct hash_value_L
+{
+    V const & v;
+
+    template<class I> std::size_t operator()( I ) const
+    {
+        boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325;
+        boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3;
+
+        // index
+
+        hv ^= I::value;
+        hv *= prime;
+
+        // value
+
+        auto const & t = unsafe_get<I::value>( v );
+
+        hv ^= std::hash<remove_cv_ref_t<decltype(t)>>()( t );
+        hv *= prime;
+
+        return static_cast<std::size_t>( hv );
+    }
+};
+
+} // namespace detail
+
+inline std::size_t hash_value( monostate const & )
+{
+    return 0xA7EE4757u;
+}
+
+template<class... T> std::size_t hash_value( variant<T...> const & v )
+{
+    return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< variant<T...> >{ v } );
+}
+
+namespace detail
+{
+
+template<class T> using is_hash_enabled = std::is_default_constructible< std::hash<typename std::remove_const<T>::type> >;
+
+template<class V, bool E = mp11::mp_all_of<V, is_hash_enabled>::value> struct std_hash_impl;
+
+template<class V> struct std_hash_impl<V, false>
+{
+    std_hash_impl() = delete;
+    std_hash_impl( std_hash_impl const& ) = delete;
+    std_hash_impl& operator=( std_hash_impl const& ) = delete;
+};
+
+template<class V> struct std_hash_impl<V, true>
+{
+    std::size_t operator()( V const & v ) const
+    {
+        return hash_value( v );
+    }
+};
+
+} // namespace detail
+
 } // namespace variant2
 } // namespace boost
 
+namespace std
+{
+
+template<class... T> struct hash< ::boost::variant2::variant<T...> >: public ::boost::variant2::detail::std_hash_impl< ::boost::variant2::variant<T...> >
+{
+};
+
+template<> struct hash< ::boost::variant2::monostate >
+{
+    std::size_t operator()( ::boost::variant2::monostate const & v ) const
+    {
+        return hash_value( v );
+    }
+};
+
+} // namespace std
+
 #if defined(_MSC_VER) && _MSC_VER < 1910
 # pragma warning( pop )
 #endif