From 61dc47e7336e5780be21427c6965dcc1cdeaa7be Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Tue, 16 Feb 2021 14:52:07 +0300 Subject: [PATCH 1/3] added optional --- module-1/homework/Optional/optional.h | 206 ++++++++++++++++++++++---- module-1/homework/Optional/tests.cpp | 17 ++- 2 files changed, 185 insertions(+), 38 deletions(-) diff --git a/module-1/homework/Optional/optional.h b/module-1/homework/Optional/optional.h index 77153ec7..f8451493 100644 --- a/module-1/homework/Optional/optional.h +++ b/module-1/homework/Optional/optional.h @@ -2,53 +2,199 @@ #include #pragma once + +namespace task { + struct nullopt_t { - // Your code goes here; + explicit constexpr nullopt_t(int) {} }; -constexpr nullopt_t // Your code goes here; +constexpr nullopt_t nullopt = nullopt_t{0}; // Your code goes here; + +template +struct in_place_type_t { + explicit in_place_type_t() = default; +}; + +template +constexpr in_place_type_t in_place_type{}; struct in_place_t { - // Your code goes here; + explicit in_place_t() = default; }; -constexpr in_place_t // Your code goes here; +constexpr in_place_t in_place = in_place_t{}; // Your code goes here; + +template +class optional_destruct_helper { +public: + constexpr optional_destruct_helper() : isEngaged(false) {} + + constexpr optional_destruct_helper(nullopt_t) : isEngaged(false) {} + + template + constexpr optional_destruct_helper(in_place_t, _Args&& ... __args): value(std::forward<_Args>(__args)...), + isEngaged(true) {} + + template + constexpr optional_destruct_helper(U&& value): value(std::forward(value)), isEngaged(true) {} + + void reset() { + isEngaged = false; + } + +protected: + union { + T value; + char __nullValue; + }; + + bool isEngaged; +}; template -class optional { - public: - - using value_type = // Your code goes here; +class optional_destruct_helper { +public: + constexpr optional_destruct_helper() : isEngaged(false) {} + + constexpr optional_destruct_helper(nullopt_t) : isEngaged(false) {} + + template + constexpr optional_destruct_helper(in_place_t, _Args&& ... __args): + value(std::forward<_Args>(__args)...), + isEngaged(true) {} + + template + constexpr optional_destruct_helper(U&& value): + value(std::forward(value)), + isEngaged(true) {} + + void reset() { + if (this->isEngaged) { + value.~T(); + } + isEngaged = false; + } + + ~optional_destruct_helper() { + if (this->isEngaged) { + value.~T(); + } + } + +protected: + union { + T value; + char __nullValue; + }; + + bool isEngaged; +}; + +template +class optional : public optional_destruct_helper> { +private: + using base = optional_destruct_helper::value>; +public: + + using value_type = T; + + constexpr optional() noexcept; + + template + constexpr optional(U&& value); - constexpr optional() noexcept; - template < class U = value_type > - constexpr optional( U&& value ); - constexpr optional(nullopt_t) noexcept; - template - constexpr explicit optional(in_place_t, _Args&&... __args); - - template - constexpr T value_or(U&& default_value) const&; + constexpr optional(nullopt_t) noexcept; - template - constexpr T value_or(U&& default_value) &&; + template + constexpr explicit optional(in_place_t, _Args&& ... __args); - constexpr bool has_value() const noexcept; + template + constexpr T value_or(U&& default_value) const&; - constexpr explicit operator bool() const noexcept; + template + constexpr T value_or(U&& default_value)&&; - constexpr std::add_pointer_t operator->() const; + constexpr bool has_value() const noexcept; - constexpr std::add_pointer_t operator->(); + constexpr explicit operator bool() const noexcept; - constexpr const value_type& operator*() const&; + constexpr std::add_pointer_t operator->() const; - constexpr value_type& operator*() &; + constexpr std::add_pointer_t operator->(); - constexpr const value_type&& operator*() const&&; + constexpr const value_type& operator*() const&; - constexpr value_type&& operator*() &&; + constexpr value_type& operator*()&; - private: - // Your code goes here; -}; \ No newline at end of file + constexpr const value_type&& operator*() const&&; + + constexpr value_type&& operator*()&&; +}; +} // task namespace + +template +constexpr task::optional::optional() noexcept: base() {} + +template +template +constexpr task::optional::optional(U&& value): base(std::forward(value)) {} + +template +constexpr task::optional::optional(nullopt_t) noexcept: base(nullopt) {} + +template +template +constexpr task::optional::optional(in_place_t, _Args&& ... __args): base(in_place, __args...) {} + +template +template +constexpr T task::optional::value_or(U&& default_value) const& { + return this->has_value() ? this->value : default_value; +} + +template +template +constexpr T task::optional::value_or(U&& default_value)&& { + return this->has_value() ? this->value : default_value; +} + +template +constexpr bool task::optional::has_value() const noexcept { + return this->isEngaged; +} + +template +constexpr task::optional::operator bool() const noexcept { + return this->has_value(); +} + +template +constexpr std::add_pointer_t::value_type> task::optional::operator->() const { + return &(this->value); +} + +template +constexpr std::add_pointer_t::value_type> task::optional::operator->() { + return &(this->value); +} + +template +constexpr const typename task::optional::value_type& task::optional::operator*() const& { + return (this->value); +} + +template +constexpr typename task::optional::value_type& task::optional::operator*()& { + return (this->value); +} + +template +constexpr const typename task::optional::value_type&& task::optional::operator*() const&& { + return this->value; +} + +template +constexpr typename task::optional::value_type&& task::optional::operator*()&& { + return this->value; +} diff --git a/module-1/homework/Optional/tests.cpp b/module-1/homework/Optional/tests.cpp index 4c25c3c8..7c5087cd 100644 --- a/module-1/homework/Optional/tests.cpp +++ b/module-1/homework/Optional/tests.cpp @@ -1,42 +1,43 @@ #include #include -#include +//#include +#include "optional.h" #include "gtest/gtest.h" TEST(ValueOR, Test1) { - std::optional opt("Hello world"); + task::optional opt("Hello world"); ASSERT_EQ(opt.value_or("empty"), "Hello world"); } TEST(ValueOR, Test2) { - std::optional opt; + task::optional opt; ASSERT_EQ(opt.value_or("empty"), "empty"); } TEST(HasValue, Test1) { - std::optional opt("Hello world"); + task::optional opt("Hello world"); ASSERT_TRUE(opt.has_value()); } TEST(Reset, Test1) { - std::optional opt("Hello world"); + task::optional opt("Hello world"); opt.reset(); ASSERT_FALSE(opt.has_value()); } TEST(ConversionToBool, Test1) { - std::optional opt("Hello world"); + task::optional opt("Hello world"); ASSERT_TRUE(opt); } TEST(ArrowOperator, Test1) { - std::optional opt("Hello world"); + task::optional opt("Hello world"); ASSERT_EQ(std::string(opt->c_str()), "Hello world"); } TEST(IndirectionOperator, Test1) { - std::optional opt(1); + task::optional opt(1); ASSERT_EQ(*opt, 1); } \ No newline at end of file From bd96893d455ddc6da81168833bec1e4ff53fffa1 Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Tue, 16 Feb 2021 15:09:27 +0300 Subject: [PATCH 2/3] Added assignment operator --- module-1/homework/Optional/optional.h | 54 ++++++++++++++++++++++++--- module-1/homework/Optional/tests.cpp | 14 +++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/module-1/homework/Optional/optional.h b/module-1/homework/Optional/optional.h index f8451493..b4338bec 100644 --- a/module-1/homework/Optional/optional.h +++ b/module-1/homework/Optional/optional.h @@ -39,11 +39,18 @@ class optional_destruct_helper { template constexpr optional_destruct_helper(U&& value): value(std::forward(value)), isEngaged(true) {} - void reset() { +protected: + void _reset() { isEngaged = false; } -protected: + template + void setValue(U&& value) { + this->value = std::forward(value); + isEngaged = true; + } + + union { T value; char __nullValue; @@ -69,20 +76,30 @@ class optional_destruct_helper { value(std::forward(value)), isEngaged(true) {} - void reset() { + + ~optional_destruct_helper() { if (this->isEngaged) { value.~T(); } - isEngaged = false; } - ~optional_destruct_helper() { +protected: + void _reset() { if (this->isEngaged) { value.~T(); } + isEngaged = false; + } + + template + void setValue(U&& value) { + if (this->isEngaged) { + this->value.~T(); + } + this->value = std::forward(value); + isEngaged = true; } -protected: union { T value; char __nullValue; @@ -109,6 +126,13 @@ class optional : public optional_destruct_helper constexpr explicit optional(in_place_t, _Args&& ... __args); + optional& operator=(nullopt_t) noexcept; + + template + optional& operator=( U&& value ); + + void reset() noexcept; + template constexpr T value_or(U&& default_value) const&; @@ -198,3 +222,21 @@ template constexpr typename task::optional::value_type&& task::optional::operator*()&& { return this->value; } + +template +task::optional& task::optional::operator=(task::nullopt_t) noexcept { + this->reset(); + return *this; +} + +template +template +task::optional& task::optional::operator=(U&& value) { + this->setValue(std::forward(value)); + return *this; +} + +template +void task::optional::reset() noexcept { + this->_reset(); +} diff --git a/module-1/homework/Optional/tests.cpp b/module-1/homework/Optional/tests.cpp index 7c5087cd..088e5198 100644 --- a/module-1/homework/Optional/tests.cpp +++ b/module-1/homework/Optional/tests.cpp @@ -6,6 +6,20 @@ #include "gtest/gtest.h" +struct MyTestStruct { + int a; + int b; +}; + +TEST(Ctor, Test1) { + task::optional testStruct(task::nullopt); + ASSERT_FALSE(testStruct.has_value()); + testStruct = {1, 2}; + ASSERT_TRUE(testStruct.has_value()); + ASSERT_EQ(testStruct->a, 1); + ASSERT_EQ(testStruct->b, 2); +} + TEST(ValueOR, Test1) { task::optional opt("Hello world"); ASSERT_EQ(opt.value_or("empty"), "Hello world"); From 9cb9b750a6d1c91c350ff27483ec4d468926f2f6 Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Tue, 16 Feb 2021 15:14:12 +0300 Subject: [PATCH 3/3] cmake fix --- module-1/homework/Optional/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module-1/homework/Optional/CMakeLists.txt b/module-1/homework/Optional/CMakeLists.txt index 7097fd40..cea3b7a6 100644 --- a/module-1/homework/Optional/CMakeLists.txt +++ b/module-1/homework/Optional/CMakeLists.txt @@ -4,7 +4,7 @@ include(GoogleTest) project("runner") -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)