diff --git a/include/boost/variant/variant_alternative.hpp b/include/boost/variant/variant_alternative.hpp new file mode 100644 index 00000000..17276ce7 --- /dev/null +++ b/include/boost/variant/variant_alternative.hpp @@ -0,0 +1,129 @@ +// Copyright (c) 2017 +// Mikhail Maximov +// +// 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) + +#ifndef BOOST_VARIANT_ALTERNATIVE_HPP +#define BOOST_VARIANT_ALTERNATIVE_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace detail { +namespace variant { + +// copies sequence to mpl::list, then uses mpl::at to get I-th type +template +struct type_in_seqeunce { + private: + typedef typename boost::mpl::insert_range< + boost::mpl::list<> + , boost::mpl::end< boost::mpl::list<> >::type + , typename Sequence::type + >::type sequence; + public: + typedef typename mpl::at< + sequence, + mpl::integral_c >::type type; +}; + +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) +// variant_alternative_impl using variadic templates + +template +struct get_type { + typedef typename get_type::type type; +}; + +template +struct get_type<0, Type, Types...> { + typedef Type type; +}; + +template +struct variant_alternative_impl { + typedef typename get_type::type type; +}; + +// variant_alternative_impl specialization for make_variant_over_sequence +template +struct variant_alternative_impl > { + typedef typename type_in_seqeunce::type type; +}; + +#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) +// variant_alternative_impl without variadic templates using BOOST_VARIANT_ENUM_PARAMS + +template +struct variant_alternative_impl: + mpl::at< + mpl::vector, + mpl::integral_c > {}; + +// variant_alternative_impl specialization for make_variant_over_sequence +template +struct variant_alternative_impl, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)> { + typedef typename type_in_seqeunce::type type; +}; + +#endif + +} // namespace variant +} // namespace detail + +template struct variant_alternative; // undefined + +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) +// variant_alternative using variadic templates + +template +struct variant_alternative> { + typedef typename detail::variant::variant_alternative_impl::type type; +}; + +#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) +// variant_alternative without variadic_templates using BOOST_VARIANT_ENUM_PARAMS + +template +struct variant_alternative > { + typedef typename detail::variant::variant_alternative_impl::type type; +}; + +#endif + +// cv-qualifiers handlers +template struct variant_alternative { + typedef typename add_const::type>::type type; +}; + +template struct variant_alternative { + typedef typename add_volatile::type>::type type; +}; + +template struct variant_alternative { + typedef typename add_cv::type>::type type; +}; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +template +using variant_alternative_t = typename variant_alternative::type; +#endif + +} // namespace boost + +#endif // BOOST_VARIANT_ALTERNATIVE_HPP \ No newline at end of file diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c071b77d..c0c15ebb 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -53,6 +53,7 @@ test-suite variant [ run overload_selection.cpp ] [ run recursive_wrapper_move_test.cpp ] [ run variant_over_joint_view_test.cpp ] + [ run variant_alternative_test.cpp ] ; diff --git a/test/variant_alternative_test.cpp b/test/variant_alternative_test.cpp new file mode 100644 index 00000000..424cda36 --- /dev/null +++ b/test/variant_alternative_test.cpp @@ -0,0 +1,97 @@ +// Copyright (c) 2017 +// Mikhail Maximov +// +// 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 + +#include "boost/config.hpp" + +#include "boost/test/minimal.hpp" +#include "boost/variant.hpp" +#include "boost/variant/variant_alternative.hpp" + +#include "boost/type_traits/add_const.hpp" +#include "boost/type_traits/add_cv.hpp" +#include "boost/type_traits/add_volatile.hpp" +#include "boost/type_traits/integral_constant.hpp" +#include "boost/type_traits/is_const.hpp" +#include "boost/type_traits/is_volatile.hpp" +#include "boost/type_traits/remove_cv.hpp" + +template +struct logical_and: boost::false_type {}; + +template<> +struct logical_and: boost::true_type {}; + +template +struct is_cv : logical_and::value, boost::is_volatile::value> {}; + +void test_correct_type() { + typedef boost::variant variant_t; + typedef typename boost::variant_alternative<0, variant_t>::type first_type; + typedef typename boost::variant_alternative<1, variant_t>::type second_type; + variant_t v; + v = 1; + BOOST_CHECK(boost::get(v) == 1); + v = "2"; + BOOST_CHECK(boost::get(v) == "2"); +} + +void test_correct_alias_type() { +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + typedef boost::variant variant_t; + typedef typename boost::variant_alternative_t<0, variant_t> first_type; + typedef typename boost::variant_alternative_t<1, variant_t> second_type; + variant_t v; + v = 1; + BOOST_CHECK(boost::get(v) == 1); + v = "2"; + BOOST_CHECK(boost::get(v) == "2"); +#endif +} + +template