diff --git a/libs/variant/test/variant.cpp b/libs/variant/test/variant.cpp new file mode 100644 index 00000000..9deaeb4f --- /dev/null +++ b/libs/variant/test/variant.cpp @@ -0,0 +1,213 @@ +#ifndef SPROUT_LIBS_VARIANT_TEST_VARIANT_CPP +#define SPROUT_LIBS_VARIANT_TEST_VARIANT_CPP + +#include +#include +#include + +namespace testspr { + static void variant_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto var1 = sprout::variant(1.0); + SPROUT_STATIC_CONSTEXPR auto var2 = sprout::variant(); + + // constructor + { + SPROUT_STATIC_CONSTEXPR auto var3 = sprout::variant(); + TESTSPR_BOTH_ASSERT(var3.which() == 0); + TESTSPR_BOTH_ASSERT(sprout::get(var3) == 0); + } + { + SPROUT_STATIC_CONSTEXPR auto var3 = sprout::variant(var1); + TESTSPR_BOTH_ASSERT(var3.which() == 1); + TESTSPR_BOTH_ASSERT(sprout::get(var3) == 1.0); + } + { + SPROUT_STATIC_CONSTEXPR auto var3 = sprout::variant(1.0); + TESTSPR_BOTH_ASSERT(var3.which() == 1); + TESTSPR_BOTH_ASSERT(sprout::get(var3) == 1.0); + } + + // swap + { + auto var3 = var1; + auto var4 = var2; + var3.swap(var4); + TESTSPR_ASSERT(var3.which() == 0); + TESTSPR_ASSERT(sprout::get(var3) == 0); + TESTSPR_ASSERT(var4.which() == 1); + TESTSPR_ASSERT(sprout::get(var4) == 1.0); + } + { + auto var3 = var1; + auto var4 = var2; + swap(var3, var4); + TESTSPR_ASSERT(var3.which() == 0); + TESTSPR_ASSERT(sprout::get(var3) == 0); + TESTSPR_ASSERT(var4.which() == 1); + TESTSPR_ASSERT(sprout::get(var4) == 1.0); + } + + // operator= + { + auto var3 = var2; + var3 = sprout::variant(1.0); + TESTSPR_ASSERT(var3.which() == 1); + TESTSPR_ASSERT(sprout::get(var3) == 1.0); + } + { + auto var3 = var2; + var3 = 1.0; + TESTSPR_ASSERT(var3.which() == 1); + TESTSPR_ASSERT(sprout::get(var3) == 1.0); + } + + // which + TESTSPR_BOTH_ASSERT(var1.which() == 1); + TESTSPR_BOTH_ASSERT(var2.which() == 0); + + // empty + TESTSPR_BOTH_ASSERT(!var1.empty()); + TESTSPR_BOTH_ASSERT(!var2.empty()); + + // operator== + TESTSPR_BOTH_ASSERT(!(var1 == var2)); + TESTSPR_BOTH_ASSERT((var1 == sprout::variant(1.0))); + + // operator!= + TESTSPR_BOTH_ASSERT(var1 != var2); + TESTSPR_BOTH_ASSERT(!(var1 != sprout::variant(1.0))); + + // operator< + TESTSPR_BOTH_ASSERT(!(var1 < var2)); + TESTSPR_BOTH_ASSERT(!(var1 < sprout::variant(0.0))); + TESTSPR_BOTH_ASSERT(!(var1 < sprout::variant(1.0))); + TESTSPR_BOTH_ASSERT((var1 < sprout::variant(2.0))); + TESTSPR_BOTH_ASSERT(!(var1 < sprout::variant(0))); + TESTSPR_BOTH_ASSERT(!(var1 < sprout::variant(1))); + TESTSPR_BOTH_ASSERT(!(var1 < sprout::variant(2))); + + // operator> + TESTSPR_BOTH_ASSERT(var1 > var2); + TESTSPR_BOTH_ASSERT((var1 > sprout::variant(0.0))); + TESTSPR_BOTH_ASSERT(!(var1 > sprout::variant(1.0))); + TESTSPR_BOTH_ASSERT(!(var1 > sprout::variant(2.0))); + TESTSPR_BOTH_ASSERT((var1 > sprout::variant(0))); + TESTSPR_BOTH_ASSERT((var1 > sprout::variant(1))); + TESTSPR_BOTH_ASSERT((var1 > sprout::variant(2))); + + // operator<= + TESTSPR_BOTH_ASSERT(!(var1 <= var2)); + TESTSPR_BOTH_ASSERT(!(var1 <= sprout::variant(0.0))); + TESTSPR_BOTH_ASSERT((var1 <= sprout::variant(1.0))); + TESTSPR_BOTH_ASSERT((var1 <= sprout::variant(2.0))); + TESTSPR_BOTH_ASSERT(!(var1 <= sprout::variant(0))); + TESTSPR_BOTH_ASSERT(!(var1 <= sprout::variant(1))); + TESTSPR_BOTH_ASSERT(!(var1 <= sprout::variant(2))); + + // operator>= + TESTSPR_BOTH_ASSERT(var1 >= var2); + TESTSPR_BOTH_ASSERT((var1 >= sprout::variant(0.0))); + TESTSPR_BOTH_ASSERT((var1 >= sprout::variant(1.0))); + TESTSPR_BOTH_ASSERT(!(var1 >= sprout::variant(2.0))); + TESTSPR_BOTH_ASSERT((var1 >= sprout::variant(0))); + TESTSPR_BOTH_ASSERT((var1 >= sprout::variant(1))); + TESTSPR_BOTH_ASSERT((var1 >= sprout::variant(2))); + + // get_at + TESTSPR_BOTH_ASSERT(var1.get_at<1>() == 1.0); + TESTSPR_BOTH_ASSERT(var2.get_at<0>() == 0); + { + auto var3 = var1; + TESTSPR_ASSERT(var3.get_at<1>() == 1.0); + } + { + auto var3 = var2; + TESTSPR_ASSERT(var3.get_at<0>() == 0); + } + + // get + TESTSPR_BOTH_ASSERT(sprout::get(var1) == 1.0); + TESTSPR_BOTH_ASSERT(sprout::get(var2) == 0); + { + auto var3 = var1; + TESTSPR_ASSERT(sprout::get(var3) == 1.0); + } + { + auto var3 = var2; + TESTSPR_ASSERT(sprout::get(var3) == 0); + } + + // apply_visitor + TESTSPR_BOTH_ASSERT(var1.apply_visitor(testspr::x2_visitor()) == 2.0); + TESTSPR_BOTH_ASSERT(var2.apply_visitor(testspr::x2_visitor()) == 0.0); + { + auto var3 = var1; + TESTSPR_ASSERT(var3.apply_visitor(testspr::x2_assign_visitor()) == 2.0); + TESTSPR_ASSERT(var3.which() == 1); + TESTSPR_ASSERT(sprout::get(var3) == 2.0); + } + { + auto var3 = var2; + TESTSPR_ASSERT(var3.apply_visitor(testspr::x2_assign_visitor()) == 0.0); + TESTSPR_ASSERT(var3.which() == 0); + TESTSPR_ASSERT(sprout::get(var3) == 0); + } + + // apply_visitor + TESTSPR_BOTH_ASSERT(sprout::apply_visitor(testspr::x2_visitor(), var1) == 2.0); + TESTSPR_BOTH_ASSERT(sprout::apply_visitor(testspr::x2_visitor(), var2) == 0.0); + { + auto var3 = var1; + TESTSPR_ASSERT(sprout::apply_visitor(testspr::x2_assign_visitor(), var3) == 2.0); + TESTSPR_ASSERT(var3.which() == 1); + TESTSPR_ASSERT(sprout::get(var3) == 2.0); + } + { + auto var3 = var2; + TESTSPR_ASSERT(sprout::apply_visitor(testspr::x2_assign_visitor(), var3) == 0.0); + TESTSPR_ASSERT(var3.which() == 0); + TESTSPR_ASSERT(sprout::get(var3) == 0); + } + + // operator<< + { + std::ostringstream os; + os << var1; + TESTSPR_ASSERT(os.str() == "1"); + } + { + std::ostringstream os; + os << var2; + TESTSPR_ASSERT(os.str() == "0"); + } + + // tuples::get + TESTSPR_BOTH_ASSERT(sprout::tuples::get<1>(var1) == 1.0); + TESTSPR_BOTH_ASSERT(sprout::tuples::get<0>(var2) == 0); + { + auto var3 = var1; + TESTSPR_ASSERT(sprout::tuples::get<1>(var3) == 1.0); + } + { + auto var3 = var2; + TESTSPR_ASSERT(sprout::tuples::get<0>(var3) == 0); + } + + // tuple_size + TESTSPR_BOTH_ASSERT(sprout::tuples::tuple_size::value == 2); + + // tuple_element + TESTSPR_BOTH_ASSERT((std::is_same::type, int const>::value)); + TESTSPR_BOTH_ASSERT((std::is_same::type, double const>::value)); + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::variant_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_VARIANT_TEST_VARIANT_CPP diff --git a/sprout/variant/io.hpp b/sprout/variant/io.hpp index 76c3f10c..7ff19c89 100644 --- a/sprout/variant/io.hpp +++ b/sprout/variant/io.hpp @@ -31,9 +31,9 @@ namespace sprout { template inline std::basic_ostream& operator<<(std::basic_ostream& lhs, sprout::variant const& rhs) { - sprout::detail::variant_output_visitor > visitor(lhs); + sprout::detail::variant_output_visitor > visitor(lhs); rhs.apply_visitor(visitor); - return lhs; + return lhs; } } // namespace sprout diff --git a/sprout/variant/variant.hpp b/sprout/variant/variant.hpp index 7f5a182a..37ed0530 100644 --- a/sprout/variant/variant.hpp +++ b/sprout/variant/variant.hpp @@ -16,9 +16,14 @@ #include namespace sprout { + template + class variant; + namespace detail { template class variant_impl { + template + friend class variant; protected: typedef sprout::tuples::tuple tuple_type; typedef sprout::types::type_tuple::type...> uncvref_tuple_type; @@ -45,6 +50,7 @@ namespace sprout { { static_assert(Index::value < sizeof...(Types), "variant<>: invalid operand"); } + public: void swap(variant_impl& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(sprout::swap(tuple_, other.tuple_))) { @@ -154,7 +160,7 @@ namespace sprout { {} // modifiers void swap(variant& other) - SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(impl_type::swap(other))) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::declval().swap(other))) { impl_type::swap(other); } @@ -244,11 +250,11 @@ namespace sprout { // visitation support template SPROUT_CONSTEXPR typename Visitor::result_type apply_visitor(Visitor&& visitor) const { - return visit(tuple_, sprout::forward(visitor), which_); + return visit<0>(tuple_, sprout::forward(visitor), which_); } template typename Visitor::result_type apply_visitor(Visitor&& visitor) { - return visit(tuple_, sprout::forward(visitor), which_); + return visit<0>(tuple_, sprout::forward(visitor), which_); } }; diff --git a/testspr/sprout.cpp b/testspr/sprout.cpp index ca5e9baa..1e4d839a 100644 --- a/testspr/sprout.cpp +++ b/testspr/sprout.cpp @@ -11,6 +11,7 @@ #include "../libs/bitset/test/bitset.cpp" #include "../libs/tuple/test/tuple.cpp" #include "../libs/optional/test/optional.cpp" +#include "../libs/variant/test/variant.cpp" #include "../libs/algorithm/test/algorithm.cpp" #include "../libs/random/test/random.cpp" @@ -25,6 +26,7 @@ namespace testspr { testspr::bitset_test(); testspr::tuple_test(); testspr::optional_test(); + testspr::variant_test(); testspr::algorithm_test(); testspr::random_test(); } diff --git a/testspr/tools.hpp b/testspr/tools.hpp index 3670c92d..99b7365c 100644 --- a/testspr/tools.hpp +++ b/testspr/tools.hpp @@ -231,6 +231,29 @@ namespace testspr { SPROUT_CONSTEXPR result operator()(T const& val) const { return result{val}; } }; + // + // x2_visitor + // + template + class x2_visitor { + public: + typedef R result_type; + public: + template + SPROUT_CONSTEXPR result_type operator()(T const& t) const { return static_cast(t + t); } + }; + // + // x2_assign_visitor + // + template + class x2_assign_visitor { + public: + typedef R result_type; + public: + template + SPROUT_CONSTEXPR result_type operator()(T& t) const { return static_cast(t += t); } + }; + // // distance //