From 0997734e5cfd1ae083d706b88af8d640f227b46f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 02:05:34 +0300 Subject: [PATCH 01/13] Make emplace constexpr --- include/boost/variant2/variant.hpp | 73 +++++++++++++++++--------- test/Jamfile | 2 + test/variant_emplace_index_cx.cpp | 83 ++++++++++++++++++++++++++++++ test/variant_emplace_type_cx.cpp | 63 +++++++++++++++++++++++ 4 files changed, 196 insertions(+), 25 deletions(-) create mode 100644 test/variant_emplace_index_cx.cpp create mode 100644 test/variant_emplace_type_cx.cpp diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index 4a0937c..ee457c9 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -342,12 +342,22 @@ template union variant_storage_impl { } - template void emplace( mp_size_t<0>, A&&... a ) noexcept + template void emplace_impl( mp_false, A&&... a ) noexcept { ::new( &first_ ) T1( std::forward(a)... ); } - template void emplace( mp_size_t, A&&... a ) noexcept + template constexpr void emplace_impl( mp_true, A&&... a ) noexcept + { + *this = variant_storage_impl( mp_size_t<0>(), std::forward(a)... ); + } + + template constexpr void emplace( mp_size_t<0>, A&&... a ) noexcept + { + this->emplace_impl( mp_all, std::is_trivially_move_assignable...>(), std::forward(a)... ); + } + + template constexpr void emplace( mp_size_t, A&&... a ) noexcept { rest_.emplace( mp_size_t(), std::forward(a)... ); } @@ -436,20 +446,25 @@ template struct variant_base_impl return st1_.get( mp_size_t() ); } - template void emplace( A&&... a ) + template constexpr void emplace_impl( mp_true, mp_bool, A&&... a ) { - std::size_t const J = I+1; + st1_.emplace( mp_size_t(), std::forward(a)... ); + ix_ = J; + } + template constexpr void emplace_impl( mp_false, mp_true, A&&... a ) + { + U tmp( std::forward(a)... ); + + st1_.emplace( mp_size_t(), std::move(tmp) ); + ix_ = J; + } + + template void emplace_impl( mp_false, mp_false, A&&... a ) + { std::size_t const K = mp_find_if, std::is_nothrow_constructible>::value; - using U = mp_at_c, I>; - - if( std::is_nothrow_constructible::value ) - { - st1_.emplace( mp_size_t(), std::forward(a)... ); - ix_ = J; - } - else if( K < sizeof...(T) ) // have nothrow destructible + if( K < sizeof...(T) ) // have nothrow destructible { try { @@ -458,8 +473,8 @@ template struct variant_base_impl } catch( ... ) { - st1_.emplace( mp_size_t() ); - ix_ = K; + st1_.emplace( mp_size_t() ); + ix_ = K+1; throw; } @@ -474,6 +489,14 @@ template struct variant_base_impl ix_ = J; } } + + template constexpr void emplace( A&&... a ) + { + std::size_t const J = I+1; + using U = mp_at_c, I>; + + this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::is_trivially_move_assignable...>(), std::forward(a)... ); + } }; // trivially destructible, double buffered @@ -516,7 +539,7 @@ template struct variant_base_impl return ix_ >= 0? st1_.get( j ): st2_.get( j ); } - template void emplace( A&&... a ) + template constexpr void emplace( A&&... a ) { size_t const J = I+1; @@ -830,7 +853,7 @@ public: } template...>, E1>> - variant( variant const& r ) + constexpr variant( variant const& r ) noexcept( mp_all...>::value ) { mp_with_index( r.index(), [&]( auto I ){ @@ -841,7 +864,7 @@ public: } template...>, E1>> - variant( variant && r ) + constexpr variant( variant && r ) noexcept( mp_all...>::value ) { mp_with_index( r.index(), [&]( auto I ){ @@ -885,7 +908,7 @@ public: // assignment template..., std::is_copy_assignable...>, E1>> - variant& operator=( variant const & r ) + constexpr variant& operator=( variant const & r ) noexcept( mp_all..., std::is_nothrow_copy_assignable...>::value ) { mp_with_index( r.index(), [&]( auto I ){ @@ -905,7 +928,7 @@ public: } template..., std::is_move_assignable...>, E1>> - variant& operator=( variant && r ) + constexpr variant& operator=( variant && r ) noexcept( mp_all..., std::is_nothrow_move_assignable...>::value ) { mp_with_index( r.index(), [&]( auto I ){ @@ -929,7 +952,7 @@ public: class V = variant2::detail::resolve_overload_type, class E2 = std::enable_if_t::value && std::is_constructible::value> > - variant& operator=( U&& u ) + constexpr variant& operator=( U&& u ) noexcept( std::is_nothrow_assignable::value && std::is_nothrow_constructible::value ) { std::size_t const I = variant2::detail::resolve_overload_index::value; @@ -949,28 +972,28 @@ public: // modifiers template, U>, class E = std::enable_if_t::value>> - U& emplace( A&&... a ) + constexpr U& emplace( A&&... a ) { variant_base::template emplace( std::forward(a)... ); return _get_impl( I() ); } template, U>, class E = std::enable_if_t&, A...>::value>> - U& emplace( std::initializer_list il, A&&... a ) + constexpr U& emplace( std::initializer_list il, A&&... a ) { variant_base::template emplace( il, std::forward(a)... ); return _get_impl( I() ); } template, I>, A...>::value>> - variant_alternative_t>& emplace( A&&... a ) + constexpr variant_alternative_t>& emplace( A&&... a ) { variant_base::template emplace( std::forward(a)... ); return _get_impl( mp_size_t() ); } template, I>, std::initializer_list&, A...>::value>> - variant_alternative_t>& emplace( std::initializer_list il, A&&... a ) + constexpr variant_alternative_t>& emplace( std::initializer_list il, A&&... a ) { variant_base::template emplace( il, std::forward(a)... ); return _get_impl( mp_size_t() ); @@ -1044,7 +1067,7 @@ public: private: - template> static variant _subset_impl( mp_size_t, V && v ) + template> static constexpr variant _subset_impl( mp_size_t, V && v ) { return variant( in_place_index, std::forward(v) ); } diff --git a/test/Jamfile b/test/Jamfile index c11eef5..b9ad29b 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -33,7 +33,9 @@ run variant_copy_assign.cpp : : : $(REQ) ; run variant_move_assign.cpp : : : $(REQ) ; run variant_value_assign.cpp : : : $(REQ) ; run variant_emplace_index.cpp : : : $(REQ) ; +compile variant_emplace_index_cx.cpp : : : $(REQ) ; run variant_emplace_type.cpp : : : $(REQ) ; +compile variant_emplace_type_cx.cpp : : : $(REQ) ; run variant_swap.cpp : : : $(REQ) ; run variant_eq_ne.cpp : : : $(REQ) ; run variant_destroy.cpp : : : $(REQ) ; diff --git a/test/variant_emplace_index_cx.cpp b/test/variant_emplace_index_cx.cpp new file mode 100644 index 0000000..3a5d73d --- /dev/null +++ b/test/variant_emplace_index_cx.cpp @@ -0,0 +1,83 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include + +using namespace boost::variant2; + +struct X +{ + int v; + constexpr X(): v( 0 ) {} + constexpr explicit X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template constexpr A test( A const& a ) +{ + V v; + + v.template emplace( a ); + + return get(v); +} + +int main() +{ + { + constexpr auto w = test, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, 1>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, 1>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, 2>( 2.0f ); + STATIC_ASSERT( w == 2.0f ); + } + + { + constexpr auto w = test, 3>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test, 4>( 4 ); + STATIC_ASSERT( w == 4 ); + } + + { + constexpr auto w = test, 5>( 5 ); + STATIC_ASSERT( w == 5 ); + } +} diff --git a/test/variant_emplace_type_cx.cpp b/test/variant_emplace_type_cx.cpp new file mode 100644 index 0000000..4162484 --- /dev/null +++ b/test/variant_emplace_type_cx.cpp @@ -0,0 +1,63 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include + +using namespace boost::variant2; + +struct X +{ + int v; + constexpr X(): v( 0 ) {} + constexpr explicit X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template constexpr A test( A const& a ) +{ + V v; + + v.template emplace( a ); + + return get(v); +} + +int main() +{ + { + constexpr auto w = test, int>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, X>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, int>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, float>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test, float>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test, X>( 1 ); + STATIC_ASSERT( w == 1 ); + } +} From 613d411396acdd86cf6bdc7c3edc8a7fcde8d7ff Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 02:27:02 +0300 Subject: [PATCH 02/13] Fix constexpr emplace on clang and msvc-14.1 --- include/boost/variant2/variant.hpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index ee457c9..c9c0d48 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -311,12 +311,12 @@ template union variant_storage_impl { } - template void emplace( mp_size_t<0>, A&&... a ) noexcept + template void emplace( mp_size_t<0>, A&&... a ) { ::new( &first_ ) T1( std::forward(a)... ); } - template void emplace( mp_size_t, A&&... a ) noexcept + template void emplace( mp_size_t, A&&... a ) { rest_.emplace( mp_size_t(), std::forward(a)... ); } @@ -342,26 +342,26 @@ template union variant_storage_impl { } - template void emplace_impl( mp_false, A&&... a ) noexcept + template void emplace_impl( mp_false, mp_size_t<0>, A&&... a ) { ::new( &first_ ) T1( std::forward(a)... ); } - template constexpr void emplace_impl( mp_true, A&&... a ) noexcept - { - *this = variant_storage_impl( mp_size_t<0>(), std::forward(a)... ); - } - - template constexpr void emplace( mp_size_t<0>, A&&... a ) noexcept - { - this->emplace_impl( mp_all, std::is_trivially_move_assignable...>(), std::forward(a)... ); - } - - template constexpr void emplace( mp_size_t, A&&... a ) noexcept + template constexpr void emplace_impl( mp_false, mp_size_t, A&&... a ) { rest_.emplace( mp_size_t(), std::forward(a)... ); } + template constexpr void emplace_impl( mp_true, mp_size_t, A&&... a ) noexcept + { + *this = variant_storage_impl( mp_size_t(), std::forward(a)... ); + } + + template constexpr void emplace( mp_size_t, A&&... a ) + { + this->emplace_impl( mp_all, std::is_trivially_move_assignable...>(), mp_size_t(), std::forward(a)... ); + } + constexpr T1& get( mp_size_t<0> ) noexcept { return first_; } constexpr T1 const& get( mp_size_t<0> ) const noexcept { return first_; } From 893cd7c1e556a37809623fe14a327a7fb2cc9365 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 03:22:31 +0300 Subject: [PATCH 03/13] Add workaround for libstdc++ < 5 --- include/boost/variant2/variant.hpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index c9c0d48..a7df153 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -359,7 +359,15 @@ template union variant_storage_impl template constexpr void emplace( mp_size_t, A&&... a ) { +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 + + this->emplace_impl( mp_all, std::has_trivial_move_assign...>(), mp_size_t(), std::forward(a)... ); + +#else + this->emplace_impl( mp_all, std::is_trivially_move_assignable...>(), mp_size_t(), std::forward(a)... ); + +#endif } constexpr T1& get( mp_size_t<0> ) noexcept { return first_; } @@ -495,7 +503,15 @@ template struct variant_base_impl std::size_t const J = I+1; using U = mp_at_c, I>; +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 + + this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::has_trivial_move_assign...>(), std::forward(a)... ); + +#else + this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::is_trivially_move_assignable...>(), std::forward(a)... ); + +#endif } }; From 7c00db06002b9b17f507adcb38fa8192fb7c3cb3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 03:44:02 +0300 Subject: [PATCH 04/13] has_trivial_move doesn't exist either in libstd++ pre-5 --- include/boost/variant2/variant.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index a7df153..5ddda9b 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -361,7 +361,7 @@ template union variant_storage_impl { #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - this->emplace_impl( mp_all, std::has_trivial_move_assign...>(), mp_size_t(), std::forward(a)... ); + this->emplace_impl( mp_all, std::has_trivial_copy_assign...>(), mp_size_t(), std::forward(a)... ); #else @@ -505,7 +505,7 @@ template struct variant_base_impl #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::has_trivial_move_assign...>(), std::forward(a)... ); + this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::has_trivial_copy_assign...>(), std::forward(a)... ); #else From 3c18ded3aabb8a7d259e21529e89108eae123cb7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 04:17:06 +0300 Subject: [PATCH 05/13] Check is_move_constructible, is_move_assignable --- include/boost/variant2/variant.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index 5ddda9b..e1c715b 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -361,7 +361,7 @@ template union variant_storage_impl { #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - this->emplace_impl( mp_all, std::has_trivial_copy_assign...>(), mp_size_t(), std::forward(a)... ); + this->emplace_impl( mp_all, std::is_move_assignable, std::has_trivial_copy_assign..., std::is_move_assignable...>(), mp_size_t(), std::forward(a)... ); #else @@ -505,7 +505,7 @@ template struct variant_base_impl #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::has_trivial_copy_assign...>(), std::forward(a)... ); + this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::is_move_constructible, std::has_trivial_copy_assign..., std::is_move_assignable...>(), std::forward(a)... ); #else From 3a198b5f2b9097346a857d5590db043dd5695d77 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 04:31:59 +0300 Subject: [PATCH 06/13] Use is_trivially_copyable instead of has_trivial_copy_* --- include/boost/variant2/variant.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index e1c715b..7c50317 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -361,7 +361,7 @@ template union variant_storage_impl { #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - this->emplace_impl( mp_all, std::is_move_assignable, std::has_trivial_copy_assign..., std::is_move_assignable...>(), mp_size_t(), std::forward(a)... ); + this->emplace_impl( mp_all, std::is_trivially_copyable, std::is_move_assignable..., std::is_trivially_copyable...>(), mp_size_t(), std::forward(a)... ); #else @@ -505,7 +505,7 @@ template struct variant_base_impl #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::is_move_constructible, std::has_trivial_copy_assign..., std::is_move_assignable...>(), std::forward(a)... ); + this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::is_move_assignable..., std::is_trivially_copyable...>(), std::forward(a)... ); #else From ca0e58f3fc088a253c71a02c450b00aca0739d58 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 04:49:44 +0300 Subject: [PATCH 07/13] is_trivially_copyable doesn't exist on 4.9 either --- include/boost/variant2/variant.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index 7c50317..6b3a70f 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -361,7 +361,7 @@ template union variant_storage_impl { #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - this->emplace_impl( mp_all, std::is_trivially_copyable, std::is_move_assignable..., std::is_trivially_copyable...>(), mp_size_t(), std::forward(a)... ); + this->emplace_impl( mp_all, std::is_trivial, std::is_move_assignable..., std::is_trivial...>(), mp_size_t(), std::forward(a)... ); #else @@ -505,7 +505,7 @@ template struct variant_base_impl #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::is_move_assignable..., std::is_trivially_copyable...>(), std::forward(a)... ); + this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::is_move_assignable..., std::is_trivial...>(), std::forward(a)... ); #else From 870dcee0a8329b89658af01158224e8546ce2380 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 05:29:22 +0300 Subject: [PATCH 08/13] Fix tests accordingly --- test/variant_emplace_index_cx.cpp | 57 +++++++++++++++++++++++++++++-- test/variant_emplace_type_cx.cpp | 30 +++++++++++++++- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/test/variant_emplace_index_cx.cpp b/test/variant_emplace_index_cx.cpp index 3a5d73d..f66f99f 100644 --- a/test/variant_emplace_index_cx.cpp +++ b/test/variant_emplace_index_cx.cpp @@ -13,9 +13,17 @@ using namespace boost::variant2; struct X { int v; - constexpr X(): v( 0 ) {} + X() = default; constexpr explicit X( int v ): v( v ) {} - constexpr operator int() const { return v; } + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr explicit Y( int v ): v( v ) {} + constexpr operator int() const { return v; } }; #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) @@ -41,6 +49,16 @@ int main() STATIC_ASSERT( w == 1 ); } +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#endif + { constexpr auto w = test, 0>( 1 ); STATIC_ASSERT( w == 1 ); @@ -80,4 +98,39 @@ int main() constexpr auto w = test, 5>( 5 ); STATIC_ASSERT( w == 5 ); } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, 1>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, 2>( 2.0f ); + STATIC_ASSERT( w == 2.0f ); + } + + { + constexpr auto w = test, 3>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test, 4>( 4 ); + STATIC_ASSERT( w == 4 ); + } + + { + constexpr auto w = test, 5>( 5 ); + STATIC_ASSERT( w == 5 ); + } + +#endif } diff --git a/test/variant_emplace_type_cx.cpp b/test/variant_emplace_type_cx.cpp index 4162484..2449b12 100644 --- a/test/variant_emplace_type_cx.cpp +++ b/test/variant_emplace_type_cx.cpp @@ -13,11 +13,19 @@ using namespace boost::variant2; struct X { int v; - constexpr X(): v( 0 ) {} + X() = default; constexpr explicit X( int v ): v( v ) {} constexpr operator int() const { return v; } }; +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr explicit Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) template constexpr A test( A const& a ) @@ -41,6 +49,16 @@ int main() STATIC_ASSERT( w == 1 ); } +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test, Y>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#endif + { constexpr auto w = test, int>( 1 ); STATIC_ASSERT( w == 1 ); @@ -60,4 +78,14 @@ int main() constexpr auto w = test, X>( 1 ); STATIC_ASSERT( w == 1 ); } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test, Y>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#endif } From 72c16ccee161a6c0be10be65ed74b62151a9bfac Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 14:58:49 +0300 Subject: [PATCH 09/13] Add test/variant_value_assign_cx --- test/Jamfile | 14 ++++ test/variant_value_assign_cx.cpp | 106 +++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 test/variant_value_assign_cx.cpp diff --git a/test/Jamfile b/test/Jamfile index b9ad29b..559f2b9 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -13,29 +13,43 @@ REQ = ; #[ requires cxx11_variadic_templates cxx11_template_aliases cxx11_declty run variant_size.cpp : : : $(REQ) ; run variant_alternative.cpp : : : $(REQ) ; + run variant_holds_alternative.cpp : : : $(REQ) ; compile variant_holds_alternative_cx.cpp : : : $(REQ) ; + run variant_get_by_index.cpp : : : $(REQ) ; compile variant_get_by_index_cx.cpp : : : $(REQ) ; + run variant_get_by_type.cpp : : : $(REQ) ; compile variant_get_by_type_cx.cpp : : : $(REQ) ; + run variant_default_construct.cpp : : : $(REQ) ; compile variant_default_construct_cx.cpp : : : $(REQ) ; + run variant_copy_construct.cpp : : : $(REQ) ; run variant_move_construct.cpp : : : $(REQ) ; + run variant_value_construct.cpp : : : $(REQ) ; compile variant_value_construct_cx.cpp : : : $(REQ) ; + run variant_in_place_index_construct.cpp : : : $(REQ) ; compile variant_in_place_index_construct_cx.cpp : : : $(REQ) ; + run variant_in_place_type_construct.cpp : : : $(REQ) ; compile variant_in_place_type_construct_cx.cpp : : : $(REQ) ; + run variant_copy_assign.cpp : : : $(REQ) ; run variant_move_assign.cpp : : : $(REQ) ; + run variant_value_assign.cpp : : : $(REQ) ; +compile variant_value_assign_cx.cpp : : : $(REQ) ; + run variant_emplace_index.cpp : : : $(REQ) ; compile variant_emplace_index_cx.cpp : : : $(REQ) ; + run variant_emplace_type.cpp : : : $(REQ) ; compile variant_emplace_type_cx.cpp : : : $(REQ) ; + run variant_swap.cpp : : : $(REQ) ; run variant_eq_ne.cpp : : : $(REQ) ; run variant_destroy.cpp : : : $(REQ) ; diff --git a/test/variant_value_assign_cx.cpp b/test/variant_value_assign_cx.cpp new file mode 100644 index 0000000..0a29a0a --- /dev/null +++ b/test/variant_value_assign_cx.cpp @@ -0,0 +1,106 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template constexpr A test( A const& a ) +{ + V v; + + v = a; + + return get(v); +} + +int main() +{ + { + constexpr auto w = test, int>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, X>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test, Y>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr auto w = test, int>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, float>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test, float>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test, X>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, X>( X(1) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test, Y>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, Y>( Y(1) ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} From 6545dc3d10ef6e86a63769670aab52ba093fadf1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 15:09:42 +0300 Subject: [PATCH 10/13] Add test/variant_copy_assign_cx --- test/Jamfile | 2 + test/variant_copy_assign_cx.cpp | 125 ++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 test/variant_copy_assign_cx.cpp diff --git a/test/Jamfile b/test/Jamfile index 559f2b9..b0dc727 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -39,6 +39,8 @@ run variant_in_place_type_construct.cpp : : : $(REQ) ; compile variant_in_place_type_construct_cx.cpp : : : $(REQ) ; run variant_copy_assign.cpp : : : $(REQ) ; +compile variant_copy_assign_cx.cpp : : : $(REQ) ; + run variant_move_assign.cpp : : : $(REQ) ; run variant_value_assign.cpp : : : $(REQ) ; diff --git a/test/variant_copy_assign_cx.cpp b/test/variant_copy_assign_cx.cpp new file mode 100644 index 0000000..21403f2 --- /dev/null +++ b/test/variant_copy_assign_cx.cpp @@ -0,0 +1,125 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if !defined( __cpp_constexpr ) || __cpp_constexpr < 201603 + +// no constexpr lambda support +int main() {} + +#else + +#include + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template constexpr T test( A const& a ) +{ + V v; + + v = a; + + return get(v); +} + +int main() +{ + { + constexpr variant v( 1 ); + constexpr auto w = test, int>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant v( 1 ); + constexpr auto w = test, X>( v ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr variant v( 1 ); + constexpr auto w = test, Y>( v ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr variant v( 1 ); + constexpr auto w = test, int>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant v( 3.0f ); + constexpr auto w = test, float>( v ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr variant v( 3.0f ); + constexpr auto w = test, float>( v ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr variant v( 1 ); + constexpr auto w = test, X>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant v( X(1) ); + constexpr auto w = test, X>( v ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr variant v( 1 ); + constexpr auto w = test, Y>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant v( Y(1) ); + constexpr auto w = test, Y>( v ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} + +#endif // constexpr lambda support From f216bb5c1f08b95ccec43003eaadacc7cca08404 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 15:13:36 +0300 Subject: [PATCH 11/13] Add test/variant_move_assign_cx --- test/Jamfile | 1 + test/variant_move_assign_cx.cpp | 116 ++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 test/variant_move_assign_cx.cpp diff --git a/test/Jamfile b/test/Jamfile index b0dc727..4830d34 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -42,6 +42,7 @@ run variant_copy_assign.cpp : : : $(REQ) ; compile variant_copy_assign_cx.cpp : : : $(REQ) ; run variant_move_assign.cpp : : : $(REQ) ; +compile variant_move_assign_cx.cpp : : : $(REQ) ; run variant_value_assign.cpp : : : $(REQ) ; compile variant_value_assign_cx.cpp : : : $(REQ) ; diff --git a/test/variant_move_assign_cx.cpp b/test/variant_move_assign_cx.cpp new file mode 100644 index 0000000..e6a6443 --- /dev/null +++ b/test/variant_move_assign_cx.cpp @@ -0,0 +1,116 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if !defined( __cpp_constexpr ) || __cpp_constexpr < 201603 + +// no constexpr lambda support +int main() {} + +#else + +#include +#include + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template constexpr T test( A&& a ) +{ + V v; + + v = std::forward(a); + + return get(v); +} + +int main() +{ + { + constexpr auto w = test, int>( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, X>( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test, Y>( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr auto w = test, int>( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, float>( variant( 3.0f ) ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test, float>( variant( 3.0f ) ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test, X>( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, X>( variant( X(1) ) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test, Y>( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test, Y>( variant( Y(1) ) ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} + +#endif // constexpr lambda support From 82104cd55e76fe0fecbc91a09eda1e0eb3de9f20 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 17:24:23 +0300 Subject: [PATCH 12/13] constexpr the copy/move constructors; change copy/move assign to not require constexpr lambdas --- include/boost/variant2/variant.hpp | 60 ++++++++++++-- test/Jamfile | 3 + test/variant_copy_assign_cx.cpp | 9 --- test/variant_copy_construct_cx.cpp | 122 +++++++++++++++++++++++++++++ test/variant_move_assign_cx.cpp | 9 --- test/variant_move_construct_cx.cpp | 113 ++++++++++++++++++++++++++ 6 files changed, 291 insertions(+), 25 deletions(-) create mode 100644 test/variant_copy_construct_cx.cpp create mode 100644 test/variant_move_construct_cx.cpp diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index 6b3a70f..4e44611 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -868,8 +868,19 @@ public: { } - template...>, E1>> - constexpr variant( variant const& r ) + template...>, E1> + > + constexpr variant( variant const& r ) noexcept + : variant_base( static_cast(r) ) + { + } + + template...>>, E1>, + class E3 = mp_if...>, E1> + > + variant( variant const& r ) noexcept( mp_all...>::value ) { mp_with_index( r.index(), [&]( auto I ){ @@ -879,8 +890,19 @@ public: }); } - template...>, E1>> - constexpr variant( variant && r ) + template...>, E1> + > + constexpr variant( variant && r ) noexcept + : variant_base( static_cast(r) ) + { + } + + template...>>, E1>, + class E3 = mp_if...>, E1> + > + variant( variant && r ) noexcept( mp_all...>::value ) { mp_with_index( r.index(), [&]( auto I ){ @@ -923,7 +945,19 @@ public: } // assignment - template..., std::is_copy_assignable...>, E1>> + template..., std::is_trivially_copy_assignable...>, E1> + > + constexpr variant& operator=( variant const & r ) noexcept + { + static_cast( *this ) = static_cast( r ); + return *this; + } + + template..., std::is_trivially_copy_assignable...>>, E1>, + class E3 = mp_if..., std::is_copy_assignable...>, E1> + > constexpr variant& operator=( variant const & r ) noexcept( mp_all..., std::is_nothrow_copy_assignable...>::value ) { @@ -943,8 +977,20 @@ public: return *this; } - template..., std::is_move_assignable...>, E1>> - constexpr variant& operator=( variant && r ) + template..., std::is_trivially_move_assignable...>, E1> + > + constexpr variant& operator=( variant && r ) noexcept + { + static_cast( *this ) = static_cast( r ); + return *this; + } + + template..., std::is_trivially_move_assignable...>>, E1>, + class E3 = mp_if..., std::is_move_assignable...>, E1> + > + variant& operator=( variant && r ) noexcept( mp_all..., std::is_nothrow_move_assignable...>::value ) { mp_with_index( r.index(), [&]( auto I ){ diff --git a/test/Jamfile b/test/Jamfile index 4830d34..39973c9 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -27,7 +27,10 @@ run variant_default_construct.cpp : : : $(REQ) ; compile variant_default_construct_cx.cpp : : : $(REQ) ; run variant_copy_construct.cpp : : : $(REQ) ; +compile variant_copy_construct_cx.cpp : : : $(REQ) ; + run variant_move_construct.cpp : : : $(REQ) ; +compile variant_move_construct_cx.cpp : : : $(REQ) ; run variant_value_construct.cpp : : : $(REQ) ; compile variant_value_construct_cx.cpp : : : $(REQ) ; diff --git a/test/variant_copy_assign_cx.cpp b/test/variant_copy_assign_cx.cpp index 21403f2..8be2579 100644 --- a/test/variant_copy_assign_cx.cpp +++ b/test/variant_copy_assign_cx.cpp @@ -6,13 +6,6 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#if !defined( __cpp_constexpr ) || __cpp_constexpr < 201603 - -// no constexpr lambda support -int main() {} - -#else - #include using namespace boost::variant2; @@ -121,5 +114,3 @@ int main() #endif } - -#endif // constexpr lambda support diff --git a/test/variant_copy_construct_cx.cpp b/test/variant_copy_construct_cx.cpp new file mode 100644 index 0000000..e208f4e --- /dev/null +++ b/test/variant_copy_construct_cx.cpp @@ -0,0 +1,122 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if !defined( __cpp_constexpr ) || __cpp_constexpr < 201603 + +// no constexpr lambda support +int main() {} + +#else + +#include + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template constexpr T test( V const& v ) +{ + V v2( v ); + return get(v); +} + +int main() +{ + { + constexpr variant v( 1 ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant v( 1 ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr variant v( 1 ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr variant v( 1 ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant v( 3.0f ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr variant v( 3.0f ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr variant v( 1 ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant v( X(1) ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr variant v( 1 ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant v( Y(1) ); + constexpr auto w = test( v ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} + +#endif // constexpr lambda support diff --git a/test/variant_move_assign_cx.cpp b/test/variant_move_assign_cx.cpp index e6a6443..d7ab65f 100644 --- a/test/variant_move_assign_cx.cpp +++ b/test/variant_move_assign_cx.cpp @@ -6,13 +6,6 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt -#if !defined( __cpp_constexpr ) || __cpp_constexpr < 201603 - -// no constexpr lambda support -int main() {} - -#else - #include #include @@ -112,5 +105,3 @@ int main() #endif } - -#endif // constexpr lambda support diff --git a/test/variant_move_construct_cx.cpp b/test/variant_move_construct_cx.cpp new file mode 100644 index 0000000..269607c --- /dev/null +++ b/test/variant_move_construct_cx.cpp @@ -0,0 +1,113 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if !defined( __cpp_constexpr ) || __cpp_constexpr < 201603 + +// no constexpr lambda support +int main() {} + +#else + +#include +#include + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template constexpr T test( V&& v ) +{ + V v2( std::forward(v) ); + return get(v); +} + +int main() +{ + { + constexpr auto w = test( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr auto w = test( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test( variant( 3.0f ) ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test( variant( 3.0f ) ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test( variant( X(1) ) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test( variant( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test( variant( Y(1) ) ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} + +#endif // constexpr lambda support From 3bb14bf93b60f1def0c741f507fe6371be137dc1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 9 Jun 2017 17:45:36 +0300 Subject: [PATCH 13/13] Add emulations for is_trivially_* traits for libstdc++ < 5 --- include/boost/variant2/variant.hpp | 65 ++++++++++++++++++------------ 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index 4e44611..260411c 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -283,6 +283,35 @@ template constexpr std::add_pointer_t get_if(varia namespace detail { +// trivially_* + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 + +template struct is_trivially_copy_constructible: mp_bool::value && std::has_trivial_copy_constructor::value> +{ +}; + +template struct is_trivially_copy_assignable: mp_bool::value && std::has_trivial_copy_assign::value> +{ +}; + +template struct is_trivially_move_constructible: mp_bool::value && std::is_trivial::value> +{ +}; + +template struct is_trivially_move_assignable: mp_bool::value && std::is_trivial::value> +{ +}; + +#else + +using std::is_trivially_copy_constructible; +using std::is_trivially_copy_assignable; +using std::is_trivially_move_constructible; +using std::is_trivially_move_assignable; + +#endif + // variant_storage template union variant_storage_impl; @@ -359,15 +388,7 @@ template union variant_storage_impl template constexpr void emplace( mp_size_t, A&&... a ) { -#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - - this->emplace_impl( mp_all, std::is_trivial, std::is_move_assignable..., std::is_trivial...>(), mp_size_t(), std::forward(a)... ); - -#else - - this->emplace_impl( mp_all, std::is_trivially_move_assignable...>(), mp_size_t(), std::forward(a)... ); - -#endif + this->emplace_impl( mp_all, variant2::detail::is_trivially_move_assignable...>(), mp_size_t(), std::forward(a)... ); } constexpr T1& get( mp_size_t<0> ) noexcept { return first_; } @@ -503,15 +524,7 @@ template struct variant_base_impl std::size_t const J = I+1; using U = mp_at_c, I>; -#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 - - this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::is_move_assignable..., std::is_trivial...>(), std::forward(a)... ); - -#else - - this->emplace_impl( std::is_nothrow_constructible(), mp_all, std::is_trivially_move_assignable...>(), std::forward(a)... ); - -#endif + this->emplace_impl( std::is_nothrow_constructible(), mp_all, variant2::detail::is_trivially_move_assignable...>(), std::forward(a)... ); } }; @@ -869,7 +882,7 @@ public: } template...>, E1> + class E2 = mp_if...>, E1> > constexpr variant( variant const& r ) noexcept : variant_base( static_cast(r) ) @@ -877,7 +890,7 @@ public: } template...>>, E1>, + class E2 = mp_if...>>, E1>, class E3 = mp_if...>, E1> > variant( variant const& r ) @@ -891,7 +904,7 @@ public: } template...>, E1> + class E2 = mp_if...>, E1> > constexpr variant( variant && r ) noexcept : variant_base( static_cast(r) ) @@ -899,7 +912,7 @@ public: } template...>>, E1>, + class E2 = mp_if...>>, E1>, class E3 = mp_if...>, E1> > variant( variant && r ) @@ -946,7 +959,7 @@ public: // assignment template..., std::is_trivially_copy_assignable...>, E1> + class E2 = mp_if..., variant2::detail::is_trivially_copy_assignable...>, E1> > constexpr variant& operator=( variant const & r ) noexcept { @@ -955,7 +968,7 @@ public: } template..., std::is_trivially_copy_assignable...>>, E1>, + class E2 = mp_if..., variant2::detail::is_trivially_copy_assignable...>>, E1>, class E3 = mp_if..., std::is_copy_assignable...>, E1> > constexpr variant& operator=( variant const & r ) @@ -978,7 +991,7 @@ public: } template..., std::is_trivially_move_assignable...>, E1> + class E2 = mp_if..., variant2::detail::is_trivially_move_assignable...>, E1> > constexpr variant& operator=( variant && r ) noexcept { @@ -987,7 +1000,7 @@ public: } template..., std::is_trivially_move_assignable...>>, E1>, + class E2 = mp_if..., variant2::detail::is_trivially_move_assignable...>>, E1>, class E3 = mp_if..., std::is_move_assignable...>, E1> > variant& operator=( variant && r )