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