diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 49d6df0..46ed39c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,6 +24,7 @@ import testing ; [ run optional_test_inplace.cpp ] [ run optional_test_io.cpp ] [ run optional_test_move.cpp ] + [ run optional_test_noexcept_move.cpp ] [ run optional_test_equals_none.cpp ] [ run optional_test_value_access.cpp ] [ run optional_test_emplace.cpp ] diff --git a/test/optional_test_move.cpp b/test/optional_test_move.cpp index affa07f..779e0c7 100644 --- a/test/optional_test_move.cpp +++ b/test/optional_test_move.cpp @@ -343,46 +343,6 @@ void test_optional_ref_to_movables() BOOST_CHECK(orm2->val == 4); } -// these 4 classes have different noexcept signatures in move operations -struct NothrowBoth { - NothrowBoth(NothrowBoth&&) BOOST_NOEXCEPT_IF(true) {}; - void operator=(NothrowBoth&&) BOOST_NOEXCEPT_IF(true) {}; -}; -struct NothrowCtor { - NothrowCtor(NothrowCtor&&) BOOST_NOEXCEPT_IF(true) {}; - void operator=(NothrowCtor&&) BOOST_NOEXCEPT_IF(false) {}; -}; -struct NothrowAssign { - NothrowAssign(NothrowAssign&&) BOOST_NOEXCEPT_IF(false) {}; - void operator=(NothrowAssign&&) BOOST_NOEXCEPT_IF(true) {}; -}; -struct NothrowNone { - NothrowNone(NothrowNone&&) BOOST_NOEXCEPT_IF(false) {}; - void operator=(NothrowNone&&) BOOST_NOEXCEPT_IF(false) {}; -}; - -#ifndef BOOST_NO_NOEXCEPT - -void test_noexcept() // this is a compile-time test -{ - BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible >::value); - BOOST_STATIC_ASSERT(::boost::is_nothrow_move_assignable >::value); - BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); - - BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible >::value); - BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable >::value); - BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); - - BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible >::value); - BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable >::value); - BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); - - BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible >::value); - BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable >::value); - BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); -} -#endif // !defned BOOST_NO_NOEXCEPT - #endif int test_main( int, char* [] ) diff --git a/test/optional_test_noexcept_move.cpp b/test/optional_test_noexcept_move.cpp new file mode 100644 index 0000000..e072785 --- /dev/null +++ b/test/optional_test_noexcept_move.cpp @@ -0,0 +1,86 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/static_assert.hpp" +#include "boost/optional/optional.hpp" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + + +using boost::optional; + + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_NO_NOEXCEPT + +// these 4 classes have different noexcept signatures in move operations +struct NothrowBoth { + NothrowBoth(NothrowBoth&&) BOOST_NOEXCEPT_IF(true) {}; + void operator=(NothrowBoth&&) BOOST_NOEXCEPT_IF(true) {}; +}; +struct NothrowCtor { + NothrowCtor(NothrowCtor&&) BOOST_NOEXCEPT_IF(true) {}; + void operator=(NothrowCtor&&) BOOST_NOEXCEPT_IF(false) {}; +}; +struct NothrowAssign { + NothrowAssign(NothrowAssign&&) BOOST_NOEXCEPT_IF(false) {}; + void operator=(NothrowAssign&&) BOOST_NOEXCEPT_IF(true) {}; +}; +struct NothrowNone { + NothrowNone(NothrowNone&&) BOOST_NOEXCEPT_IF(false) {}; + void operator=(NothrowNone&&) BOOST_NOEXCEPT_IF(false) {}; +}; + +void test_noexcept_as_defined() // this is a compile-time test +{ + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_assignable::value); + + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable::value); + + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_assignable::value); + + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable::value); +} + +void test_noexcept_on_optional() // this is a compile-time test +{ + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible >::value); + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_assignable >::value); + BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); + + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible >::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable >::value); + BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); + + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible >::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable >::value); + BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); + + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible >::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable >::value); + BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); +} + +#endif // !defned BOOST_NO_NOEXCEPT +#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES + +int main() +{ + return 0; +} + + diff --git a/test/optional_test_ref.cpp b/test/optional_test_ref.cpp index c01b08e..830840b 100644 --- a/test/optional_test_ref.cpp +++ b/test/optional_test_ref.cpp @@ -278,51 +278,12 @@ void test_relops( T const* ) BOOST_CHECK ( opt1 >= opt0 ) ; } -template -void test_none( T const* ) -{ - TRACE( std::endl << BOOST_CURRENT_FUNCTION ); - - using boost::none ; - - T a(1234); - - optional def0 ; - optional def1(none) ; - optional non_def(a) ; - - BOOST_CHECK ( def0 == none ) ; - BOOST_CHECK ( non_def != none ) ; - BOOST_CHECK ( !def1 ) ; - - non_def = none ; - BOOST_CHECK ( !non_def ) ; -} - -template -void test_arrow( T const* ) -{ - TRACE( std::endl << BOOST_CURRENT_FUNCTION ); - - T a(1234); - - optional oa(a) ; - optional const coa(a) ; - - BOOST_CHECK ( coa->V() == 1234 ) ; - - oa->V() = 4321 ; - - BOOST_CHECK ( a.V() = 4321 ) ; -} - void test_with_builtin_types() { TRACE( std::endl << BOOST_CURRENT_FUNCTION ); test_basics( ARG(double) ); test_relops( ARG(double) ) ; - test_none ( ARG(double) ) ; } void test_with_class_type() @@ -331,8 +292,6 @@ void test_with_class_type() test_basics( ARG(X) ); test_relops( ARG(X) ) ; - test_none ( ARG(X) ) ; - test_arrow ( ARG(X) ) ; BOOST_CHECK ( X::count == 0 ) ; } diff --git a/test/optional_test_ref_portable_minimum.cpp b/test/optional_test_ref_portable_minimum.cpp index 8555723..4439d8c 100644 --- a/test/optional_test_ref_portable_minimum.cpp +++ b/test/optional_test_ref_portable_minimum.cpp @@ -16,8 +16,8 @@ #endif #include "boost/core/addressof.hpp" +#include "boost/core/enable_if.hpp" #include "boost/core/lightweight_test.hpp" -#include "boost/none.hpp" using boost::optional; using boost::none; @@ -25,8 +25,9 @@ using boost::none; // testable classes struct ScopeGuard // no copy/move ctor/assign { - int val; - explicit ScopeGuard(int v) : val(v) {} + int val_; + explicit ScopeGuard(int v) : val_(v) {} + int& val() { return val_; } private: ScopeGuard(ScopeGuard const&); @@ -38,6 +39,7 @@ struct Abstract virtual int& val() = 0; virtual ~Abstract() {} Abstract(){} + private: Abstract(Abstract const&); void operator=(Abstract const&); @@ -62,9 +64,44 @@ struct concrete_type_of typedef Impl type; }; +template +struct has_arrow +{ + static const bool value = true; +}; + +template <> +struct has_arrow +{ + static const bool value = false; +}; + int& val(int& i) { return i; } int& val(Abstract& a) { return a.val(); } -int& val(ScopeGuard& g) { return g.val; } +int& val(ScopeGuard& g) { return g.val(); } + +// end testable classes + +template +typename boost::enable_if< has_arrow >::type +test_arrow() +{ + typename concrete_type_of::type v(2); + optional o(v); + BOOST_TEST(o); + BOOST_TEST_EQ(o->val(), 2); + + o->val() = 3; + BOOST_TEST(o); + BOOST_TEST_EQ(o->val(), 3); + BOOST_TEST_EQ(v.val(), 3); +} + +template +typename boost::disable_if< has_arrow >::type +test_arrow() +{ +} template void test_not_containing_value_for() @@ -91,17 +128,41 @@ void test_direct_init_for() BOOST_TEST(o); BOOST_TEST(o != none); BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); - BOOST_TEST(val(*o) == val(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 2); val(v) = 9; BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); - BOOST_TEST(val(*o) == val(v)); - BOOST_TEST(val(*o) == 9); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 9); + BOOST_TEST_EQ(val(v), 9); val(*o) = 7; BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); - BOOST_TEST(val(*o) == val(v)); - BOOST_TEST(val(*o) == 7); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 7); + BOOST_TEST_EQ(val(v), 7); +} + +template +void test_clearing_the_value() +{ + typename concrete_type_of::type v(2); + optional o1(v), o2(v); + + BOOST_TEST(o1); + BOOST_TEST(o1 != none); + BOOST_TEST(o2); + BOOST_TEST(o2 != none); + + o1 = none; + BOOST_TEST(!o1); + BOOST_TEST(o1 == none); + BOOST_TEST(o2); + BOOST_TEST(o2 != none); + BOOST_TEST_EQ(val(*o2), 2); + BOOST_TEST(boost::addressof(*o2) == boost::addressof(v)); + BOOST_TEST_EQ(val(v), 2); } template @@ -119,13 +180,46 @@ void test_copy_assignment_for() val(v) = 9; BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); - BOOST_TEST(val(*o) == val(v)); - BOOST_TEST(val(*o) == 9); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 9); + BOOST_TEST_EQ(val(v), 9); val(*o) = 7; BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); - BOOST_TEST(val(*o) == val(v)); - BOOST_TEST(val(*o) == 7); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 7); + BOOST_TEST_EQ(val(v), 7); +} + +template +void test_rebinding_assignment_semantics() +{ + typename concrete_type_of::type v(2), w(7); + optional o(v); + + BOOST_TEST(o); + BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 2); + + o = optional(w); + BOOST_TEST_EQ(val(v), 2); + + BOOST_TEST(o); + BOOST_TEST(boost::addressof(*o) != boost::addressof(v)); + BOOST_TEST_NE(val(*o), val(v)); + BOOST_TEST_NE(val(*o), 2); + + BOOST_TEST(boost::addressof(*o) == boost::addressof(w)); + BOOST_TEST_EQ(val(*o), val(w)); + BOOST_TEST_EQ(val(*o), 7); + + val(*o) = 8; + BOOST_TEST(boost::addressof(*o) == boost::addressof(w)); + BOOST_TEST_EQ(val(*o), val(w)); + BOOST_TEST_EQ(val(*o), 8); + BOOST_TEST_EQ(val(w), 8); + BOOST_TEST_EQ(val(v), 2); } @@ -135,13 +229,16 @@ void test_optional_ref() test_not_containing_value_for(); test_direct_init_for(); test_copy_assignment_for(); + test_rebinding_assignment_semantics(); + test_clearing_the_value(); + test_arrow(); } int main() { test_optional_ref(); test_optional_ref(); - test_optional_ref(); + //test_optional_ref(); return boost::report_errors(); } diff --git a/test/optional_test_value_access.cpp b/test/optional_test_value_access.cpp index 63d65b9..1759588 100644 --- a/test/optional_test_value_access.cpp +++ b/test/optional_test_value_access.cpp @@ -8,18 +8,6 @@ // // You are welcome to contact the author at: // akrzemi1@gmail.com -// -// Revisions: -// -#include -#include -#include - -#define BOOST_ENABLE_ASSERT_HANDLER - -#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin -#include "boost/mpl/bool.hpp" -#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_ #include "boost/optional/optional.hpp" @@ -27,11 +15,10 @@ #pragma hdrstop #endif -#include "boost/none.hpp" +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" -#include "boost/test/minimal.hpp" - -#include "optional_test_common.cpp" +using boost::optional; struct IntWrapper { @@ -48,10 +35,10 @@ void test_function_value_or_for() optional oM1(1); const optional oC2(2); - BOOST_CHECK(oM0.value_or(5) == 5); - BOOST_CHECK(oC0.value_or(5) == 5); - BOOST_CHECK(oM1.value_or(5) == 1); - BOOST_CHECK(oC2.value_or(5) == 2); + BOOST_TEST(oM0.value_or(5) == 5); + BOOST_TEST(oC0.value_or(5) == 5); + BOOST_TEST(oM1.value_or(5) == 1); + BOOST_TEST(oC2.value_or(5) == 2); } template @@ -64,36 +51,24 @@ void test_function_value_for() try { T& v = o1.value(); - BOOST_CHECK(v == 1); + BOOST_TEST(v == 1); } catch(...) { - BOOST_CHECK(false); + BOOST_TEST(false); } try { T const& v = oC.value(); - BOOST_CHECK(v == 2); + BOOST_TEST(v == 2); } catch(...) { - BOOST_CHECK(false); + BOOST_TEST(false); } - try - { - T& v = o0.value(); - BOOST_CHECK(false); - boost::ignore_unused(v); - } - catch(boost::bad_optional_access const&) - { - } - catch(...) - { - BOOST_CHECK(false); - } + BOOST_TEST_THROWS(o0.value(), boost::bad_optional_access); } void test_function_value() @@ -120,12 +95,12 @@ void test_function_value_or() test_function_value_or_for(); optional oi(1); - BOOST_CHECK(oi.value_or(FatToIntConverter(2)) == 1); - BOOST_CHECK(FatToIntConverter::conversions == 0); + BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 1); + BOOST_TEST(FatToIntConverter::conversions == 0); oi = boost::none; - BOOST_CHECK(oi.value_or(FatToIntConverter(2)) == 2); - BOOST_CHECK(FatToIntConverter::conversions == 1); + BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 2); + BOOST_TEST(FatToIntConverter::conversions == 1); } @@ -156,42 +131,34 @@ void test_function_value_or_eval() FunM funM; FunC funC; - BOOST_CHECK(o1.value_or_eval(funM) == 1); - BOOST_CHECK(oN.value_or_eval(funM) == 5); - BOOST_CHECK(o1.value_or_eval(FunM()) == 1); - BOOST_CHECK(oN.value_or_eval(FunM()) == 5); + BOOST_TEST_EQ(o1.value_or_eval(funM), 1); + BOOST_TEST_EQ(oN.value_or_eval(funM), 5); + BOOST_TEST_EQ(o1.value_or_eval(FunM()), 1); + BOOST_TEST_EQ(oN.value_or_eval(FunM()), 5); - BOOST_CHECK(o1.value_or_eval(funC) == 1); - BOOST_CHECK(oN.value_or_eval(funC) == 6); - BOOST_CHECK(o1.value_or_eval(FunC()) == 1); - BOOST_CHECK(oN.value_or_eval(FunC()) == 6); + BOOST_TEST_EQ(o1.value_or_eval(funC), 1); + BOOST_TEST_EQ(oN.value_or_eval(funC), 6); + BOOST_TEST_EQ(o1.value_or_eval(FunC()), 1); + BOOST_TEST_EQ(oN.value_or_eval(FunC()), 6); - BOOST_CHECK(o1.value_or_eval(funP) == 1); - BOOST_CHECK(oN.value_or_eval(funP) == 7); + BOOST_TEST_EQ(o1.value_or_eval(funP), 1); + BOOST_TEST_EQ(oN.value_or_eval(funP), 7); #ifndef BOOST_NO_CXX11_LAMBDAS - BOOST_CHECK(o1.value_or_eval([](){return 8;}) == 1); - BOOST_CHECK(oN.value_or_eval([](){return 8;}) == 8); + BOOST_TEST_EQ(o1.value_or_eval([](){return 8;}), 1); + BOOST_TEST_EQ(oN.value_or_eval([](){return 8;}), 8); #endif try { - BOOST_CHECK(o1.value_or_eval(throw_) == 1); + BOOST_TEST_EQ(o1.value_or_eval(throw_), 1); } catch(...) { - BOOST_CHECK(false); + BOOST_TEST(false); } - try - { - BOOST_CHECK(oN.value_or_eval(throw_) == 1); - BOOST_CHECK(false); - } - catch(...) - { - BOOST_CHECK(true); - } + BOOST_TEST_THROWS(oN.value_or_eval(throw_), int); } const optional makeConstOptVal() @@ -244,21 +211,12 @@ void test_move_only_getters() #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS -int test_main( int, char* [] ) +int main() { - try - { - test_function_value(); - test_function_value_or(); - test_function_value_or_eval(); - test_const_move(); - } - catch ( ... ) - { - BOOST_ERROR("Unexpected Exception caught!"); - } + test_function_value(); + test_function_value_or(); + test_function_value_or_eval(); + test_const_move(); - return 0; + return boost::report_errors(); } - -