Compare commits

..

4 Commits

Author SHA1 Message Date
Peter Dimov
f39a71ed2f Merge branch 'feature/issue-26-nofix' into feature/issue-26 2021-03-13 01:09:46 +02:00
Peter Dimov
06dde96400 Merge branch 'develop' into feature/issue-26-nofix 2021-03-13 01:09:17 +02:00
Peter Dimov
90cda5339f Disable U&& constructor for derived types 2021-03-12 23:40:14 +02:00
Peter Dimov
f586dc8848 Add test for inherited constructors (refs #26) 2021-03-12 20:15:09 +02:00
4 changed files with 54 additions and 63 deletions

View File

@@ -26,7 +26,6 @@
#include <initializer_list>
#include <utility>
#include <functional> // std::hash
#include <cstdint>
//
@@ -39,8 +38,6 @@ BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
#endif
template<class T> struct hash;
namespace variant2
{
@@ -1584,7 +1581,7 @@ public:
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,
class E1 = typename std::enable_if< !std::is_same<Ud, variant>::value && !std::is_base_of<variant, Ud>::value && !detail::is_in_place_index<Ud>::value && !detail::is_in_place_type<Ud>::value >::type,
class V = detail::resolve_overload_type<U&&, T...>,
class E2 = typename std::enable_if<std::is_constructible<V, U&&>::value>::type
>
@@ -2198,59 +2195,31 @@ void swap( variant<T...> & v, variant<T...> & w )
namespace detail
{
inline std::size_t hash_value_impl_( mp11::mp_true, std::size_t index, std::size_t value )
{
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;
hv ^= index;
hv *= prime;
hv ^= value;
hv *= prime;
return static_cast<std::size_t>( hv );
}
inline std::size_t hash_value_impl_( mp11::mp_false, std::size_t index, std::size_t value )
{
std::size_t hv = 0x811C9DC5;
std::size_t const prime = 0x01000193;
hv ^= index;
hv *= prime;
hv ^= value;
hv *= prime;
return hv;
}
inline std::size_t hash_value_impl( std::size_t index, std::size_t value )
{
return hash_value_impl_( mp11::mp_bool< (SIZE_MAX > UINT32_MAX) >(), index, value );
}
template<template<class> class H, class V> struct hash_value_L
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 );
std::size_t index = I::value;
std::size_t value = H<remove_cv_ref_t<decltype(t)>>()( t );
hv ^= std::hash<remove_cv_ref_t<decltype(t)>>()( t );
hv *= prime;
return hash_value_impl( index, value );
return static_cast<std::size_t>( hv );
}
};
template<class... T> std::size_t hash_value_std( variant<T...> const & v )
{
return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< std::hash, variant<T...> >{ v } );
}
} // namespace detail
inline std::size_t hash_value( monostate const & )
@@ -2260,7 +2229,7 @@ inline std::size_t hash_value( monostate const & )
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< boost::hash, variant<T...> >{ v } );
return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< variant<T...> >{ v } );
}
namespace detail
@@ -2281,7 +2250,7 @@ template<class V> struct std_hash_impl<V, true>
{
std::size_t operator()( V const & v ) const
{
return detail::hash_value_std( v );
return hash_value( v );
}
};

View File

@@ -119,3 +119,5 @@ run variant_visit_r.cpp : : :
<toolset>gcc,<target-os>windows:<variant>release
<toolset>gcc,<target-os>cygwin:<variant>release
;
compile variant_derived_construct.cpp ;

View File

@@ -0,0 +1,33 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/variant2/variant.hpp>
using namespace boost::variant2;
template<class... T> class X: variant<T...>
{
using base = variant<T...>;
using base::base;
};
struct Y
{
Y( Y const& rhs ) = default;
template<class T> Y( T const& t )
{
t.bar();
}
};
int main()
{
using W = X<int, double, Y>;
W a( 1 );
W b( a );
(void)b;
}

View File

@@ -12,7 +12,6 @@
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/config/workaround.hpp>
#include <vector>
using namespace boost::variant2;
@@ -48,17 +47,7 @@ template<template<class...> class Hash, class T> void test2()
BOOST_TEST_NE( h2, h3 );
}
struct X
{
int m = 0;
};
std::size_t hash_value( X const& x )
{
return boost::hash<int>()( x.m );
}
struct Y {}; // no hash support
struct X {};
int main()
{
@@ -68,8 +57,6 @@ int main()
test<boost::hash, monostate, monostate, monostate>();
test<boost::hash, int, int, float>();
test<boost::hash, monostate, X, std::vector<X>>();
test2<std::hash, int>();
test2<std::hash, float>();
@@ -78,7 +65,7 @@ int main()
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1910) && ( !defined(_LIBCPP_STD_VER) || _LIBCPP_STD_VER > 11 )
BOOST_TEST_TRAIT_FALSE(( detail::is_hash_enabled<Y> ));
BOOST_TEST_TRAIT_FALSE(( detail::is_hash_enabled<X> ));
#endif