Add test/variant_copy_construct, variant_move_construct

This commit is contained in:
Peter Dimov
2017-05-30 03:45:55 +03:00
parent 084712cab3
commit 5aa16c5bf7
4 changed files with 276 additions and 23 deletions

View File

@ -642,8 +642,13 @@ public:
});
}
template<class U> constexpr variant( U&& u )
noexcept( std::is_nothrow_constructible< variant2::detail::resolve_overload_type<U&&, T...>, U >::value )
template<class U,
class E1 = std::enable_if_t<!std::is_same<std::decay_t<U>, variant>::value>,
class V = variant2::detail::resolve_overload_type<U&&, T...>,
class E2 = std::enable_if_t<std::is_constructible<V, U>::value>
>
constexpr variant( U&& u )
noexcept( std::is_nothrow_constructible<V, U>::value )
: variant_base( variant2::detail::resolve_overload_index<U&&, T...>(), std::forward<U>(u) )
{
}
@ -714,9 +719,9 @@ public:
template<class U,
class E1 = std::enable_if_t<!std::is_same<std::decay_t<U>, variant>::value>,
class V = variant2::detail::resolve_overload_type<U, T...>,
class E2 = std::enable_if_t<std::is_assignable<V&, U>::value && std::is_constructible<V&, U>::value>
class E2 = std::enable_if_t<std::is_assignable<V&, U>::value && std::is_constructible<V, U>::value>
>
variant& operator=( U&& u ) // noexcept(see below );
variant& operator=( U&& u ) noexcept( std::is_nothrow_assignable<V&, U>::value && std::is_nothrow_constructible<V, U>::value )
{
std::size_t const I = variant2::detail::resolve_overload_index<U, T...>::value;
@ -733,7 +738,6 @@ public:
}
// modifiers
// using variant_base::emplace;
template<class U, class... A, class I = mp_find<variant<T...>, U>> U& emplace( A&&... a )
{
@ -777,28 +781,30 @@ template<class... T> constexpr bool operator==( variant<T...> const & v, variant
{
if( v.index() != w.index() ) return false;
bool r = false;
mp_for_each<mp_iota_c<sizeof...(T)>>([&]( auto I ){
if( I == v.index() ) return get<I>(v) == get<I>(w);
if( I == v.index() ) r = get<I>(v) == get<I>(w);
});
assert( false );
return false;
return r;
}
template<class... T> constexpr bool operator!=( variant<T...> const & v, variant<T...> const & w )
{
if( v.index() != w.index() ) return true;
bool r = true;
mp_for_each<mp_iota_c<sizeof...(T)>>([&]( auto I ){
if( I == v.index() ) return get<I>(v) != get<I>(w);
if( I == v.index() ) r = get<I>(v) != get<I>(w);
});
assert( false );
return true;
return r;
}
template<class... T> constexpr bool operator<( variant<T...> const & v, variant<T...> const & w )
@ -806,14 +812,15 @@ template<class... T> constexpr bool operator<( variant<T...> const & v, variant<
if( v.index() < w.index() ) return true;
if( v.index() > w.index() ) return false;
bool r = false;
mp_for_each<mp_iota_c<sizeof...(T)>>([&]( auto I ){
if( I == v.index() ) return get<I>(v) < get<I>(w);
if( I == v.index() ) r = get<I>(v) < get<I>(w);
});
assert( false );
return false;
return r;
}
template<class... T> constexpr bool operator>( variant<T...> const & v, variant<T...> const & w )
@ -821,14 +828,15 @@ template<class... T> constexpr bool operator>( variant<T...> const & v, variant
if( v.index() > w.index() ) return true;
if( v.index() < w.index() ) return false;
bool r = false;
mp_for_each<mp_iota_c<sizeof...(T)>>([&]( auto I ){
if( I == v.index() ) return get<I>(v) > get<I>(w);
if( I == v.index() ) r = get<I>(v) > get<I>(w);
});
assert( false );
return false;
return r;
}
template<class... T> constexpr bool operator<=( variant<T...> const & v, variant<T...> const & w )
@ -836,14 +844,15 @@ template<class... T> constexpr bool operator<=( variant<T...> const & v, variant
if( v.index() < w.index() ) return true;
if( v.index() > w.index() ) return false;
bool r = false;
mp_for_each<mp_iota_c<sizeof...(T)>>([&]( auto I ){
if( I == v.index() ) return get<I>(v) <= get<I>(w);
if( I == v.index() ) r = get<I>(v) <= get<I>(w);
});
assert( false );
return false;
return r;
}
template<class... T> constexpr bool operator>=( variant<T...> const & v, variant<T...> const & w )
@ -851,14 +860,15 @@ template<class... T> constexpr bool operator>=( variant<T...> const & v, variant
if( v.index() > w.index() ) return true;
if( v.index() < w.index() ) return false;
bool r = false;
mp_for_each<mp_iota_c<sizeof...(T)>>([&]( auto I ){
if( I == v.index() ) return get<I>(v) >= get<I>(w);
if( I == v.index() ) r = get<I>(v) >= get<I>(w);
});
assert( false );
return false;
return r;
}
// visitation

View File

@ -21,3 +21,5 @@ run get_by_type.cpp : : : $(REQ) ;
compile 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) ;

View File

@ -0,0 +1,120 @@
// 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 <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <type_traits>
#include <utility>
#include <string>
using namespace boost::variant2;
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
struct X1
{
X1() {}
X1(X1 const&) {}
X1(X1&&) {}
};
inline bool operator==( X1, X1 ) { return true; }
STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value );
STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value );
STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value );
struct X2
{
X2() {}
X2(X2 const&) {}
X2(X2&&) {}
};
inline bool operator==( X2, X2 ) { return true; }
STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value );
STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value );
STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value );
template<class V> static void test( V const & v )
{
V v2( v );
BOOST_TEST_EQ( v.index(), v2.index() );
BOOST_TEST( v == v2 );
}
int main()
{
test( variant<int>() );
test( variant<int>(1) );
test( variant<int const>() );
test( variant<int const>(1) );
test( variant<int, float>() );
test( variant<int, float>(1) );
test( variant<int, float>(3.14f) );
test( variant<int, float, std::string>() );
test( variant<int, float, std::string>(1) );
test( variant<int, float, std::string>(3.14f) );
test( variant<int, float, std::string>("test") );
test( variant<int, int>() );
test( variant<int, int, float>() );
test( variant<int, int, float>(3.14f) );
test( variant<int, int, float, float>() );
test( variant<int, int, float, float, std::string>("test") );
test( variant<std::string, std::string, float>() );
test( variant<X1, X2>() );
test( variant<X1, X2, int>() );
test( variant<X1, X2, X2>() );
test( variant<X1, X1, X2, X2>() );
{
variant<X1, X2> v;
v.emplace<X2>();
test( v );
}
{
variant<X1, X1, X2> v;
v.emplace<X2>();
test( v );
}
{
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int const>>));
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int, float>>));
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int, int, float, float>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1, int>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1, int, float>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<int, X1>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<int, int, X1>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1, X2>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1, X2, int, int>>));
}
return boost::report_errors();
}

View File

@ -0,0 +1,121 @@
// 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 <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <type_traits>
#include <utility>
#include <string>
using namespace boost::variant2;
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
struct X1
{
X1() {}
X1(X1 const&) {}
X1(X1&&) {}
};
inline bool operator==( X1, X1 ) { return true; }
STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value );
STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value );
STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value );
struct X2
{
X2() {}
X2(X2 const&) {}
X2(X2&&) {}
};
inline bool operator==( X2, X2 ) { return true; }
STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value );
STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value );
STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value );
template<class V> static void test( V&& v )
{
V v2( v );
V v3( std::move(v) );
BOOST_TEST_EQ( v2.index(), v3.index() );
BOOST_TEST( v2 == v3 );
}
int main()
{
test( variant<int>() );
test( variant<int>(1) );
test( variant<int const>() );
test( variant<int const>(1) );
test( variant<int, float>() );
test( variant<int, float>(1) );
test( variant<int, float>(3.14f) );
test( variant<int, float, std::string>() );
test( variant<int, float, std::string>(1) );
test( variant<int, float, std::string>(3.14f) );
test( variant<int, float, std::string>("test") );
test( variant<int, int>() );
test( variant<int, int, float>() );
test( variant<int, int, float>(3.14f) );
test( variant<int, int, float, float>() );
test( variant<int, int, float, float, std::string>("test") );
test( variant<std::string, std::string, float>() );
test( variant<X1, X2>() );
test( variant<X1, X2, int>() );
test( variant<X1, X2, X2>() );
test( variant<X1, X1, X2, X2>() );
{
variant<X1, X2> v;
v.emplace<X2>();
test( std::move(v) );
}
{
variant<X1, X1, X2> v;
v.emplace<X2>();
test( std::move(v) );
}
{
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int const>>));
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int, float>>));
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int, int, float, float>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1, int>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1, int, float>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<int, X1>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<int, int, X1>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1, X2>>));
BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1, X2, int, int>>));
}
return boost::report_errors();
}