diff --git a/libs/optional/test/optional.cpp b/libs/optional/test/optional.cpp new file mode 100644 index 00000000..1ef8c6a6 --- /dev/null +++ b/libs/optional/test/optional.cpp @@ -0,0 +1,315 @@ +#ifndef SPROUT_LIBS_OPTIONAL_TEST_OPTIONAL_CPP +#define SPROUT_LIBS_OPTIONAL_TEST_OPTIONAL_CPP + +#include +#include +#include + +namespace testspr { + static void optional_test() { + using namespace sprout; + { + SPROUT_STATIC_CONSTEXPR auto opt1 = sprout::optional(1234); + SPROUT_STATIC_CONSTEXPR auto opt2 = sprout::optional(); + + // constructor + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::optional(); + TESTSPR_BOTH_ASSERT(!opt3); + } + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::optional(1234); + TESTSPR_BOTH_ASSERT(!!opt3); + } + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::optional(sprout::nullopt); + TESTSPR_BOTH_ASSERT(!opt3); + } + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::optional(sprout::nullopt); + TESTSPR_BOTH_ASSERT(!opt3); + } + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::optional(false, 1234); + TESTSPR_BOTH_ASSERT(!opt3); + + SPROUT_STATIC_CONSTEXPR auto opt4 = sprout::optional(true, 1234); + TESTSPR_BOTH_ASSERT(!!opt4); + TESTSPR_BOTH_ASSERT(opt4.get() == 1234); + } + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::optional(opt1); + TESTSPR_BOTH_ASSERT(!!opt3); + TESTSPR_BOTH_ASSERT(opt3.get() == 1234); + } + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::optional(sprout::optional(1234)); + TESTSPR_BOTH_ASSERT(!!opt3); + TESTSPR_BOTH_ASSERT(opt3.get() == 1234); + } + + // operator= + { + auto opt3 = sprout::optional(1234); + opt3 = sprout::nullopt; + TESTSPR_ASSERT(!opt3); + } + { + auto opt3 = sprout::optional(); + opt3 = 1234; + TESTSPR_ASSERT(!!opt3); + TESTSPR_ASSERT(opt3.get() == 1234); + } + { + auto opt3 = sprout::optional(); + opt3 = opt1; + TESTSPR_ASSERT(!!opt3); + TESTSPR_ASSERT(opt3.get() == 1234); + } + { + auto opt3 = sprout::optional(); + opt3 = sprout::optional(1234); + TESTSPR_ASSERT(!!opt3); + TESTSPR_ASSERT(opt3.get() == 1234); + } + + // assign + { + auto opt3 = sprout::optional(1234); + opt3.assign(sprout::nullopt); + TESTSPR_ASSERT(!opt3); + } + { + auto opt3 = sprout::optional(); + opt3.assign(1234); + TESTSPR_ASSERT(!!opt3); + TESTSPR_ASSERT(opt3.get() == 1234); + } + { + auto opt3 = sprout::optional(); + opt3.assign(opt1); + TESTSPR_ASSERT(!!opt3); + TESTSPR_ASSERT(opt3.get() == 1234); + } + { + auto opt3 = sprout::optional(); + opt3.assign(sprout::optional(1234)); + TESTSPR_ASSERT(!!opt3); + TESTSPR_ASSERT(opt3.get() == 1234); + } + + // reset + { + auto opt3 = sprout::optional(1234); + opt3.reset(); + TESTSPR_ASSERT(!opt3); + } + { + auto opt3 = sprout::optional(1234); + opt3.reset(sprout::nullopt); + TESTSPR_ASSERT(!opt3); + } + { + auto opt3 = sprout::optional(); + opt3.reset(1234); + TESTSPR_ASSERT(!!opt3); + TESTSPR_ASSERT(opt3.get() == 1234); + } + + // swap + { + auto opt3 = sprout::optional(1234); + auto opt4 = sprout::optional(); + opt3.swap(opt4); + TESTSPR_ASSERT(!opt3); + TESTSPR_ASSERT(!!opt4); + TESTSPR_ASSERT(opt4.get() == 1234); + } + { + auto opt3 = sprout::optional(1234); + auto opt4 = sprout::optional(); + swap(opt3, opt4); + TESTSPR_ASSERT(!opt3); + TESTSPR_ASSERT(!!opt4); + TESTSPR_ASSERT(opt4.get() == 1234); + } + + // operator* + TESTSPR_BOTH_ASSERT(*opt1 == 1234); + { + auto opt3 = sprout::optional(1234); + TESTSPR_ASSERT(*opt3 == 1234); + + *opt3 = 12345; + TESTSPR_ASSERT(*opt3 == 12345); + } + + // get + TESTSPR_BOTH_ASSERT(opt1.get() == 1234); + { + auto opt3 = sprout::optional(1234); + TESTSPR_ASSERT(opt3.get() == 1234); + + opt3.get() = 12345; + TESTSPR_ASSERT(opt3.get() == 12345); + } + + // get_value_or + TESTSPR_BOTH_ASSERT(opt1.get_value_or(12345) == 1234); + TESTSPR_BOTH_ASSERT(opt2.get_value_or(12345) == 12345); + { + auto opt3 = sprout::optional(1234); + int v = 12345; + TESTSPR_ASSERT(opt3.get_value_or(v) == 1234); + } + { + auto opt3 = sprout::optional(); + int v = 12345; + TESTSPR_ASSERT(opt3.get_value_or(v) == 12345); + } + + // operator-> + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::make_optional(testspr::is_odd()); + TESTSPR_BOTH_ASSERT(opt3->operator()(123)); + } + { + auto opt3 = sprout::make_optional(testspr::is_odd()); + TESTSPR_ASSERT(opt3->operator()(123)); + } + + // get_pointer + TESTSPR_BOTH_ASSERT(*opt1.get_pointer() == 1234); + { + auto opt3 = sprout::optional(1234); + TESTSPR_ASSERT(*opt3.get_pointer() == 1234); + + opt3.get() = 12345; + TESTSPR_ASSERT(*opt3.get_pointer() == 12345); + } + + // get_ptr + TESTSPR_BOTH_ASSERT(*opt1.get_ptr() == 1234); + { + auto opt3 = sprout::optional(1234); + TESTSPR_ASSERT(*opt3.get_ptr() == 1234); + + opt3.get() = 12345; + TESTSPR_ASSERT(*opt3.get_ptr() == 12345); + } + + // operator bool + TESTSPR_BOTH_ASSERT(static_cast(opt1)); + TESTSPR_BOTH_ASSERT(!static_cast(opt2)); + + // operator! + TESTSPR_BOTH_ASSERT(!!opt1); + TESTSPR_BOTH_ASSERT(!opt2); + + // is_initialized + TESTSPR_BOTH_ASSERT(opt1.is_initialized()); + TESTSPR_BOTH_ASSERT(!opt2.is_initialized()); + + // make_optional + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::make_optional(1234); + TESTSPR_BOTH_ASSERT(!!opt3); + TESTSPR_BOTH_ASSERT(opt3.get() == 1234); + } + { + SPROUT_STATIC_CONSTEXPR auto opt3 = sprout::make_optional(false, 1234); + TESTSPR_BOTH_ASSERT(!opt3); + + SPROUT_STATIC_CONSTEXPR auto opt4 = sprout::make_optional(true, 1234); + TESTSPR_BOTH_ASSERT(!!opt4); + TESTSPR_BOTH_ASSERT(opt4.get() == 1234); + } + + // operator== + TESTSPR_BOTH_ASSERT(!(opt1 == opt2)); + TESTSPR_BOTH_ASSERT(opt1 == sprout::optional(1234)); + + // operator!= + TESTSPR_BOTH_ASSERT(opt1 != opt2); + TESTSPR_BOTH_ASSERT(!(opt1 != sprout::optional(1234))); + + // operator< + TESTSPR_BOTH_ASSERT(!(opt1 < opt2)); + TESTSPR_BOTH_ASSERT(!(opt1 < sprout::optional())); + TESTSPR_BOTH_ASSERT(!(opt1 < sprout::optional(123))); + TESTSPR_BOTH_ASSERT(!(opt1 < sprout::optional(1234))); + TESTSPR_BOTH_ASSERT(opt1 < sprout::optional(12345)); + TESTSPR_BOTH_ASSERT(!(opt2 < sprout::optional())); + TESTSPR_BOTH_ASSERT(opt2 < sprout::optional(123)); + TESTSPR_BOTH_ASSERT(opt2 < sprout::optional(1234)); + TESTSPR_BOTH_ASSERT(opt2 < sprout::optional(12345)); + + // operator> + TESTSPR_BOTH_ASSERT(opt1 > opt2); + TESTSPR_BOTH_ASSERT(opt1 > sprout::optional()); + TESTSPR_BOTH_ASSERT(opt1 > sprout::optional(123)); + TESTSPR_BOTH_ASSERT(!(opt1 > sprout::optional(1234))); + TESTSPR_BOTH_ASSERT(!(opt1 > sprout::optional(12345))); + TESTSPR_BOTH_ASSERT(!(opt2 > sprout::optional())); + TESTSPR_BOTH_ASSERT(!(opt2 > sprout::optional(123))); + TESTSPR_BOTH_ASSERT(!(opt2 > sprout::optional(1234))); + TESTSPR_BOTH_ASSERT(!(opt2 > sprout::optional(12345))); + + // operator<= + TESTSPR_BOTH_ASSERT(!(opt1 <= opt2)); + TESTSPR_BOTH_ASSERT(!(opt1 <= sprout::optional())); + TESTSPR_BOTH_ASSERT(!(opt1 <= sprout::optional(123))); + TESTSPR_BOTH_ASSERT(opt1 <= sprout::optional(1234)); + TESTSPR_BOTH_ASSERT(opt1 <= sprout::optional(12345)); + TESTSPR_BOTH_ASSERT(opt2 <= sprout::optional()); + TESTSPR_BOTH_ASSERT(opt2 <= sprout::optional(123)); + TESTSPR_BOTH_ASSERT(opt2 <= sprout::optional(1234)); + TESTSPR_BOTH_ASSERT(opt2 <= sprout::optional(12345)); + + // operator>= + TESTSPR_BOTH_ASSERT(opt1 >= opt2); + TESTSPR_BOTH_ASSERT(opt1 >= sprout::optional()); + TESTSPR_BOTH_ASSERT(opt1 >= sprout::optional(123)); + TESTSPR_BOTH_ASSERT(opt1 >= sprout::optional(1234)); + TESTSPR_BOTH_ASSERT(!(opt1 >= sprout::optional(12345))); + TESTSPR_BOTH_ASSERT(opt2 >= sprout::optional()); + TESTSPR_BOTH_ASSERT(!(opt2 >= sprout::optional(123))); + TESTSPR_BOTH_ASSERT(!(opt2 >= sprout::optional(1234))); + TESTSPR_BOTH_ASSERT(!(opt2 >= sprout::optional(12345))); + + // operator<< + { + std::ostringstream os; + os << opt1; + TESTSPR_ASSERT(os.str() == " 1234"); + } + { + std::ostringstream os; + os << opt2; + TESTSPR_ASSERT(os.str() == "--"); + } + + // operator>> + { + std::istringstream is(" 1234"); + auto opt3 = sprout::optional(); + is >> opt3; + TESTSPR_ASSERT(!!opt3); + TESTSPR_ASSERT(opt3.get() == 1234); + } + { + std::istringstream is("--"); + auto opt3 = sprout::optional(1234); + is >> opt3; + TESTSPR_ASSERT(!opt3); + } + } + } +} // namespace testspr + +#ifndef TESTSPR_CPP_INCLUDE +# define TESTSPR_TEST_FUNCTION testspr::optional_test +# include +#endif + +#endif // #ifndef SPROUT_LIBS_OPTIONAL_TEST_OPTIONAL_CPP diff --git a/sprout/optional/io.hpp b/sprout/optional/io.hpp index a7bcb53c..e562ff29 100644 --- a/sprout/optional/io.hpp +++ b/sprout/optional/io.hpp @@ -13,7 +13,7 @@ namespace sprout { // template inline std::basic_istream& - operator<<(std::basic_istream& lhs, sprout::optional& rhs) { + operator>>(std::basic_istream& lhs, sprout::optional& rhs) { if (lhs.good()) { int d = lhs.get(); if (d == ' ') { diff --git a/sprout/optional/optional.hpp b/sprout/optional/optional.hpp index 952c60ac..19c3b14e 100644 --- a/sprout/optional/optional.hpp +++ b/sprout/optional/optional.hpp @@ -55,10 +55,10 @@ namespace sprout { : init(v.init) , val(v.val) {} - template + template explicit SPROUT_CONSTEXPR optional(optional const& v) - : init(v.init) - , val(v.val.get()) + : init(v.is_initialized()) + , val(v.get()) {} optional& operator=(sprout::nullopt_t v) SPROUT_NOEXCEPT { @@ -73,7 +73,7 @@ namespace sprout { assign(v); return *this; } - template + template optional& operator=(optional const& v) { assign(v); return *this; @@ -84,16 +84,16 @@ namespace sprout { } void assign(argument_type v) { optional temp(v); - temp.swap(v); + temp.swap(*this); } void assign(optional const& v) { optional temp(v); - temp.swap(v); + temp.swap(*this); } - template + template void assign(optional const& v) { optional temp(v); - temp.swap(v); + temp.swap(*this); } void reset() SPROUT_NOEXCEPT { @@ -113,14 +113,20 @@ namespace sprout { sprout::swap(val, other.val); } + SPROUT_CONSTEXPR reference_const_type operator*() const { + return get(); + } + reference_type operator*() { + return get(); + } SPROUT_CONSTEXPR reference_const_type get() const { return is_initialized() ? val.get() - : throw std::domain_error("optional: value not initialized") + : (throw std::domain_error("optional: value not initialized"), val.get()) ; } reference_type get() { return is_initialized() ? val.get() - : throw std::domain_error("optional: value not initialized") + : (throw std::domain_error("optional: value not initialized"), val.get()) ; } SPROUT_CONSTEXPR reference_const_type get_value_or(reference_const_type& v) const { diff --git a/sprout/utility/value_holder/value_holder.hpp b/sprout/utility/value_holder/value_holder.hpp index 3efb3ab7..26d7bee3 100644 --- a/sprout/utility/value_holder/value_holder.hpp +++ b/sprout/utility/value_holder/value_holder.hpp @@ -138,8 +138,10 @@ namespace sprout { private: holder_type holder_; public: - value_holder() = default; - value_holder(value_holder const&) = default; + SPROUT_CONSTEXPR value_holder() + : holder_() + {} + SPROUT_CONSTEXPR value_holder(value_holder const&) = default; explicit SPROUT_CONSTEXPR value_holder(param_type p) : holder_(helper_type::hold(p)) {} diff --git a/testspr/sprout.cpp b/testspr/sprout.cpp index e140a2c3..57639832 100644 --- a/testspr/sprout.cpp +++ b/testspr/sprout.cpp @@ -9,6 +9,7 @@ #include "../libs/array/test/array.cpp" #include "../libs/string/test/string.cpp" #include "../libs/bitset/test/bitset.cpp" +#include "../libs/optional/test/optional.cpp" #include "../libs/algorithm/test/algorithm.cpp" #include "../libs/random/test/random.cpp" @@ -21,6 +22,7 @@ namespace testspr { testspr::array_test(); testspr::string_test(); testspr::bitset_test(); + testspr::optional_test(); testspr::algorithm_test(); testspr::random_test(); }