#include #include #include #include #include /* Implement Optional here */ int main() { { Optional o { }; assert( !o.is_valid() ); o = 5; assert( o.is_valid() ); assert( o.get_value() == 5 ); // test that a reference is returned o.get_value() = 3; assert( o.get_value() == 3 ); o.clear(); assert( !o.is_valid() ); } { // save a large std::string Optional o { std::string(1000, '-') }; assert( o.is_valid() ); assert(( o.get_value() == std::string(1000, '-') )); auto previous_capacity = o.get_value().capacity(); // here the destructor of the stored string must be called... o.clear(); assert( !o.is_valid() ); o = ""; assert( o.is_valid() ); assert( o.get_value().empty() ); // ... due to the destructor of the string having been called previously // the number of allocated bytes in the new string must be different. // // If this test fails that means you are still re-using the same string // object as the beginning of the testcase, this is incorrect. assert( o.get_value().capacity() != previous_capacity ); } // test copy operations { Optional> o1 { std::vector { 1, 2, 3 } }; Optional> o2 { }; Optional> o3 { o1 }; // copy o1 Optional> o4 { o2 }; // copy o2 assert( o3.is_valid() ); assert( o3.get_value() == o1.get_value() ); // make sure that the copied value is a deep copy assert( &o3.get_value() != &o1.get_value() ); assert( !o4.is_valid() ); // copy o1 into o4 o4 = o1; assert( o4.is_valid() ); assert( o4.get_value() == o1.get_value() ); // make sure that the copied value is a deep copy assert( &o4.get_value() != &o1.get_value() ); // create a new, different optional Optional> o5 { std::vector{ 4, 5, 6, 7 } }; // overwrite existing values o3 = o5; assert( o3.is_valid() ); assert( o3.get_value() == o5.get_value() ); // make sure that the copied value is a deep copy assert( &o3.get_value() != &o5.get_value() ); // clear out previous value with empty optional o4 = Optional>{ }; assert( !o4.is_valid() ); } }