/* Copyright 2024 Joaquin M Lopez Munoz. * 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) * * See http://www.boost.org/libs/poly_collection for library home page. */ #include "test_fixed_variant.hpp" #include #include #include #include #include #include #include #include #include #include #include #include "test_utilities.hpp" using namespace test_utilities; struct non_copyable { constexpr non_copyable(int=0){}; non_copyable(const non_copyable&)=delete; non_copyable(non_copyable&&)=default; constexpr bool operator==(const non_copyable&)const{return true;} constexpr bool operator!=(const non_copyable&)const{return false;} constexpr bool operator<(const non_copyable&)const{return false;} constexpr bool operator<=(const non_copyable&)const{return true;} constexpr bool operator>(const non_copyable&)const{return false;} constexpr bool operator>=(const non_copyable&)const{return true;} }; std::size_t hash_value(const non_copyable&){return 0;} struct get_addresses { using result_type=std::pair; template result_type operator()(const T& x,const Q& y)const{return {&x,&y};} }; enum cref_qualifier_value { plain_ref=0, const_ref, rvalue_ref, const_rvalue_ref, }; template cref_qualifier_value cref_qualifier(T&) {return plain_ref;} template cref_qualifier_value cref_qualifier(const T&) {return const_ref;} template cref_qualifier_value cref_qualifier(T&&) {return rvalue_ref;} template cref_qualifier_value cref_qualifier(const T&&) {return const_rvalue_ref;} struct get_cref_qualifiers { using result_type=std::pair; template result_type operator()(T&& x,Q&& y)const { return { cref_qualifier(std::forward(x)),cref_qualifier(std::forward(y)) }; } }; struct hasher_helper { std::size_t& seed; template void operator()(const T& x){boost::hash_combine(seed,x);} }; struct hasher { hasher(std::size_t seed_=0):seed{seed_}{} template std::size_t operator()(const Ts&... xs)const { std::size_t res=seed; boost::mp11::tuple_for_each( std::forward_as_tuple(xs...),hasher_helper{res}); return res; } std::size_t seed; }; template using iota_tuple=boost::mp11::mp_repeat_c,N>; template iota_tuple make_iota_tuple(boost::mp11::index_sequence) { return iota_tuple{T{Is}...}; } template iota_tuple make_iota_tuple() { return make_iota_tuple(boost::mp11::make_index_sequence{}); } template struct visitor_by_index { V&& x; template auto operator()(Fs&&... fs)-> decltype(visit_by_index(std::forward(x),std::forward(fs)...)) { return visit_by_index(std::forward(x),std::forward(fs)...); } }; template struct void_visitor_by_index { V&& x; template void operator()(Fs&&... fs) { using boost::poly_collection::visit_by_index; return visit_by_index(std::forward(x),std::forward(fs)...); } }; #if BOOST_WORKAROUND(BOOST_GCC_VERSION,<50000) template struct get_ { V& v; void operator()() { using namespace boost::poly_collection; (void)get(v); } }; #endif template void test_fixed_variant_for() { using namespace boost::poly_collection; static constexpr std::size_t I=boost::mp11::mp_find::value; static constexpr std::size_t J=I!=1?1:2; using Q=boost::mp11::mp_at_c; fixed_variant_impl::fixed_variant_closure x{T(0)},y{T(1)}; fixed_variant_impl::fixed_variant_closure z{Q(2)}; V &v=x,&w=y; const V &cv=v,&cw=w,&cu=z; BOOST_TEST(cv.index()==I); BOOST_TEST(!cv.valueless_by_exception()); BOOST_TEST((cv==cw) == (x==y)); BOOST_TEST((cv!=cw) == (x!=y)); BOOST_TEST((cv< cw) == (x< y)); BOOST_TEST((cv<=cw) == (x<=y)); BOOST_TEST((cv> cw) == (x> y)); BOOST_TEST((cv>=cw) == (x>=y)); BOOST_TEST((cv==cu) == (I==J)); BOOST_TEST((cv!=cu) == (I!=J)); BOOST_TEST((cv< cu) == (I< J)); BOOST_TEST((cv<=cu) == (I<=J)); BOOST_TEST((cv> cu) == (I> J)); BOOST_TEST((cv>=cu) == (I>=J)); BOOST_TEST_TRAIT_TRUE(( std::is_base_of,variant_size>)); BOOST_TEST_TRAIT_TRUE(( std::is_base_of,variant_size>)); #ifndef BOOST_NO_CXX14_VARIABLE_TEMPLATES BOOST_TEST_TRAIT_TRUE((std::integral_constant< bool,boost::mp11::mp_size::value==variant_size_v>)); BOOST_TEST_TRAIT_TRUE((std::integral_constant< bool,boost::mp11::mp_size::value==variant_size_v>)); #endif BOOST_TEST_TRAIT_TRUE(( std::is_same::type,T>)); BOOST_TEST_TRAIT_TRUE(( std::is_same::type,const T>)); BOOST_TEST_TRAIT_TRUE(( std::is_same::type,T&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same::type,const T&&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same,T>)); BOOST_TEST_TRAIT_TRUE(( std::is_same,const T>)); BOOST_TEST_TRAIT_TRUE(( std::is_same,T&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same,const T&&>)); BOOST_TEST(( visit(get_addresses{},v,w)==get_addresses::result_type{&x,&y})); #if BOOST_WORKAROUND(BOOST_GCC_VERSION,<40900) /* call of overloaded 'cref_qualifier(...&)' is ambiguous */ #else BOOST_TEST(( visit(get_cref_qualifiers{},v,cv)== get_cref_qualifiers::result_type{plain_ref,const_ref})); BOOST_TEST(( visit(get_cref_qualifiers{},std::move(v),std::move(cv))== get_cref_qualifiers::result_type{rvalue_ref,const_rvalue_ref})); #endif BOOST_TEST( visit(hasher{},cv,cw,cu)==hasher{}(x.value,y.value,z.value)); BOOST_TEST( visit(hasher{},cv,cw,cv,cu)==hasher{}(x.value,y.value,x.value,z.value)); visit(hasher{}); visit(hasher{},cv); visit(hasher{},cv,cw); visit(hasher{},cv,cw,cu); BOOST_TEST( boost::mp11::tuple_apply( visitor_by_index{cv}, make_iota_tuple::value>())== hasher{I}(x.value)); boost::mp11::tuple_apply( void_visitor_by_index{cv}, make_iota_tuple::value>()); BOOST_TEST(holds_alternative(cv)); BOOST_TEST(!holds_alternative(cv)); BOOST_TEST(&get(v)==&x.value); BOOST_TEST(&get(cv)==&x.value); BOOST_TEST(get(std::move(v))==x.value); BOOST_TEST(get(std::move(cv))==x.value); check_throw([&]{(void)get(v);}); BOOST_TEST(&get(v)==&x.value); BOOST_TEST(&get(cv)==&x.value); BOOST_TEST(get(std::move(v))==x.value); BOOST_TEST(get(std::move(cv))==x.value); #if BOOST_WORKAROUND(BOOST_GCC_VERSION,<50000) /* https://godbolt.org/z/jcfKb755o */ check_throw(get_{v}); #else check_throw([&]{(void)get(v);}); #endif BOOST_TEST(get_if((V*)nullptr)==nullptr); BOOST_TEST(get_if(&v)==&x.value); BOOST_TEST(get_if(&cv)==&x.value); BOOST_TEST(get_if(&v)==nullptr); BOOST_TEST(get_if((V*)nullptr)==nullptr); BOOST_TEST(get_if(&v)==&x.value); BOOST_TEST(get_if(&cv)==&x.value); BOOST_TEST(get_if(&v)==nullptr); BOOST_TEST_TRAIT_TRUE(( std::is_same(v)),T&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(cv)),const T&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(std::move(v))),T&&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(std::move(cv))),const T&&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(v)),T&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(cv)),const T&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(v))),T&&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(cv))),const T&&>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(&v)),T*>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(&cv)),const T*>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(&v)),T*>)); BOOST_TEST_TRAIT_TRUE(( std::is_same(&cv)),const T*>)); } template void test_fixed_variant() { using variant_type=boost::poly_collection::fixed_variant_impl:: fixed_variant; do_((test_fixed_variant_for(),0)...); } void test_fixed_variant() { test_fixed_variant(); }