From 5472be17791249ffbbb233e4db5e558fae259ff6 Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Sat, 6 Mar 2021 14:18:02 +0300 Subject: [PATCH 1/7] completed Variant --- module-1/homework/Variant/tests.cpp | 16 ++- module-1/homework/Variant/variant.h | 182 ++++++++++++++++++++++++++-- 2 files changed, 183 insertions(+), 15 deletions(-) diff --git a/module-1/homework/Variant/tests.cpp b/module-1/homework/Variant/tests.cpp index a6099b36..2af47220 100644 --- a/module-1/homework/Variant/tests.cpp +++ b/module-1/homework/Variant/tests.cpp @@ -7,24 +7,32 @@ TEST(Get, Test1) { variant v; + //v = std::string("Hello world"); v = "Hello world"; - ASSERT_EQ(std::get(v),"Hello world"); + ASSERT_EQ(get(v),"Hello world"); +} + +TEST(Get, Test1_1) { + variant v; + v = std::string("Hello world"); + ASSERT_EQ(get(v),"Hello world"); } TEST(Get, Test2) { variant v; v = 12.0; - ASSERT_NEAR(std::get(v), 12.0, 1e-5); + ASSERT_NEAR(get(v), 12.0, 1e-5); } + TEST(Get, Test3) { variant v; v = "Hello world"; - ASSERT_EQ(std::get<2>(v), "Hello world"); + ASSERT_EQ(get<2>(v), "Hello world"); } TEST(Get, Test4) { variant v; v = 12.0; - ASSERT_NEAR(std::get<1>(v), 12.0, 1e-5); + ASSERT_NEAR(get<1>(v), 12.0, 1e-5); } \ No newline at end of file diff --git a/module-1/homework/Variant/variant.h b/module-1/homework/Variant/variant.h index 8c1e2c31..c7c77e60 100644 --- a/module-1/homework/Variant/variant.h +++ b/module-1/homework/Variant/variant.h @@ -2,6 +2,75 @@ #pragma once +template +constexpr void static_print() { +#if !defined(__GNUC__) || defined(__clang__) + int static_print_is_implemented_only_for_gcc = 0; +#else + int unused = 0; +#endif +}; + +template +union __union; + +template +union __union { + +}; + +struct __union_helper { + template + static constexpr auto&& get(U&& v, std::in_place_index_t<0>) { + return std::forward(v).head; + } + + template + static constexpr auto&& get(U&& v, std::in_place_index_t) { + return get(std::forward(v).tail, std::in_place_index); + } + + template + static void set(U&& value, std::in_place_index_t<0>, __union& u) { + if (std::is_same_v) { + u.head = value; + } else if (std::is_convertible_v) { + u.head = (Head)value; + } + } + + template + static void set(U&& value, std::in_place_index_t, __union& u) { + set(std::forward(value), std::in_place_index, u.tail); + } +}; + + +template +union __union { +public: + + T head; + __union tail; + + __union() { + if (!std::is_trivially_constructible_v) { + head = T(); + } + } + + ~__union() { + if (!std::is_trivially_destructible_v) { + head.~T(); + } + if (!std::is_trivially_destructible_v) { + tail.~decltype(tail)(); + } + } + + friend struct __union_helper; +}; + template class variant; @@ -11,35 +80,126 @@ struct variant_alternative; template using variant_alternative_t = typename variant_alternative::type; -template -struct variant_alternative> { - using type = // Your code goes here +static constexpr int not_founded = -1; + +template +auto test_implicitly_convertible(int) -> decltype( + void(std::declval()(std::declval())), std::true_type{} +); + +template +auto test_implicitly_convertible(...) -> std::false_type; + +template +struct is_implicitly_convertible : std::integral_constant(0))::value> {}; + +template +constexpr std::size_t find_type_pos( + std::size_t cur_pos, + const bool (&founded)[SizeofFounded], + const bool (&constr)[SizeofFounded] + ) { + return (cur_pos == SizeofFounded) ? not_founded : + ((founded[cur_pos] || constr[cur_pos]) ? cur_pos : find_type_pos(cur_pos + 1, founded, constr)); +} + +template +constexpr std::size_t find_type_pos( + std::size_t cur_pos, + const bool (&founded)[SizeofFounded] +) { + return (cur_pos == SizeofFounded) ? not_founded : + ((founded[cur_pos]) ? cur_pos : find_type_pos(cur_pos + 1, founded)); +} + +template +struct find_exactly_one_checked_ { + constexpr static bool founded[sizeof...(Types)] = {std::is_same::value...}; + constexpr static bool constructible[sizeof...(Types)] = {is_implicitly_convertible::value...}; + constexpr static std::size_t valueForAssignment = find_type_pos(0, founded) == -1 ? find_type_pos(0, founded, constructible) : find_type_pos(0, founded);//find_type_pos(0, founded); + constexpr static std::size_t value = find_type_pos(0, founded);//find_type_pos(0, founded); +}; + +template +struct find_exactly_one_t : public find_exactly_one_checked_ {}; + +template +struct Typelist{ + typedef head Head; + typedef Typelist Tail; +}; + +template struct TypeAt; + +template +struct TypeAt<0, Typelist> { + typedef Head Result; +}; +template +struct TypeAt> { + typedef typename TypeAt>::Result Result; +}; + +template +struct variant_alternative> { + using type = typename TypeAt>::Result;// Your code goes here }; + +template +auto&& generic_get(variant& v) { + return __union_helper::get(std::forward>(v).data_, std::in_place_index::value>); +} + template class variant { - - public: +public: // Special member functions constexpr variant() noexcept; template variant& operator=( T&& t ) noexcept; - - private: + + template friend + auto&& generic_get(variant& v); +private: // Your code goes here + __union<0, Types...> data_; }; +template +template +variant& variant::operator=(T&& t) noexcept { + constexpr auto value = find_exactly_one_t::valueForAssignment; + static_assert(value != -1); + static_print(); + __union_helper::set(std::forward(t), std::in_place_index, this->data_); + return *this; +} + +template +constexpr variant::variant() noexcept {}; + + // Non-member functions template -constexpr variant_alternative_t>& get(variant& v); +constexpr const variant_alternative_t>& get(variant& v) { + return generic_get>::Result>(std::forward(v)); +} template -constexpr variant_alternative_t>&& get(variant&& v); +constexpr variant_alternative_t>&& get(variant&& v) { + return generic_get>::Result>(std::move(v)); +} template -constexpr T& get(variant& v); +constexpr const T& get(variant& v) { + return generic_get(v); +} template -constexpr T&& get( variant&& v ); \ No newline at end of file +constexpr T&& get( variant&& v ) { + return generic_get(std::move(v)); +} \ No newline at end of file From 6870e6aa645bb9060766fe344b0e4b2ab8464160 Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Sat, 6 Mar 2021 14:22:41 +0300 Subject: [PATCH 2/7] fix --- module-1/homework/Variant/tests.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module-1/homework/Variant/tests.cpp b/module-1/homework/Variant/tests.cpp index ee6f1595..df9fda53 100644 --- a/module-1/homework/Variant/tests.cpp +++ b/module-1/homework/Variant/tests.cpp @@ -20,20 +20,20 @@ TEST(Get, Test1_1) { } TEST(Get, Test2) { - task::variant v; + variant v; v = 12.0; ASSERT_NEAR(get(v), 12.0, 1e-5); } TEST(Get, Test3) { - task::variant v; + variant v; v = "Hello world"; ASSERT_EQ(get<2>(v), "Hello world"); } TEST(Get, Test4) { - task::variant v; + variant v; v = 12.0; ASSERT_NEAR(get<1>(v), 12.0, 1e-5); } \ No newline at end of file From 9abdcba82e87ffdf28c9641288a37ff50db80ab7 Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Sat, 6 Mar 2021 14:25:34 +0300 Subject: [PATCH 3/7] added #include --- module-1/homework/Variant/variant.h | 1 + 1 file changed, 1 insertion(+) diff --git a/module-1/homework/Variant/variant.h b/module-1/homework/Variant/variant.h index 679e06be..9f577f8d 100644 --- a/module-1/homework/Variant/variant.h +++ b/module-1/homework/Variant/variant.h @@ -1,4 +1,5 @@ #include +#include #pragma once From 0758d148e92ff2c0ba43f2493e6a646b6e958f35 Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Sat, 6 Mar 2021 14:37:26 +0300 Subject: [PATCH 4/7] fix --- module-1/homework/Variant/variant.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module-1/homework/Variant/variant.h b/module-1/homework/Variant/variant.h index 9f577f8d..def1bc20 100644 --- a/module-1/homework/Variant/variant.h +++ b/module-1/homework/Variant/variant.h @@ -65,7 +65,7 @@ union __union { head.~T(); } if (!std::is_trivially_destructible_v) { - tail.~decltype(tail)(); + tail.~__union(); } } From 441dbb9830522150d2f2818212f314f5f272c1a9 Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Sat, 6 Mar 2021 14:38:50 +0300 Subject: [PATCH 5/7] fix --- module-1/homework/Variant/variant.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/module-1/homework/Variant/variant.h b/module-1/homework/Variant/variant.h index def1bc20..401ad1c0 100644 --- a/module-1/homework/Variant/variant.h +++ b/module-1/homework/Variant/variant.h @@ -64,9 +64,6 @@ union __union { if (!std::is_trivially_destructible_v) { head.~T(); } - if (!std::is_trivially_destructible_v) { - tail.~__union(); - } } friend struct __union_helper; From 408327c4f9bfb48d612ef0c14326b17312ed02d5 Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Sat, 6 Mar 2021 14:42:12 +0300 Subject: [PATCH 6/7] enhancement --- module-1/homework/Variant/variant.h | 35 +++++++++++------------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/module-1/homework/Variant/variant.h b/module-1/homework/Variant/variant.h index 401ad1c0..6a65c7e2 100644 --- a/module-1/homework/Variant/variant.h +++ b/module-1/homework/Variant/variant.h @@ -3,14 +3,17 @@ #pragma once -template -constexpr void static_print() { -#if !defined(__GNUC__) || defined(__clang__) - int static_print_is_implemented_only_for_gcc = 0; -#else - int unused = 0; -#endif -}; +template +auto test_implicitly_convertible(int) -> decltype( +void(std::declval()(std::declval())), std::true_type{} +); + +template +auto test_implicitly_convertible(...) -> std::false_type; + +template +struct is_implicitly_convertible : std::integral_constant(0))::value> {}; template union __union; @@ -35,8 +38,8 @@ struct __union_helper { static void set(U&& value, std::in_place_index_t<0>, __union& u) { if (std::is_same_v) { u.head = value; - } else if (std::is_convertible_v) { - u.head = (Head)value; + } else if (is_implicitly_convertible::value) { + u.head = value; } } @@ -80,17 +83,6 @@ using variant_alternative_t = typename variant_alternative::type; static constexpr int not_founded = -1; -template -auto test_implicitly_convertible(int) -> decltype( - void(std::declval()(std::declval())), std::true_type{} -); - -template -auto test_implicitly_convertible(...) -> std::false_type; - -template -struct is_implicitly_convertible : std::integral_constant(0))::value> {}; template constexpr std::size_t find_type_pos( @@ -172,7 +164,6 @@ template variant& variant::operator=(T&& t) noexcept { constexpr auto value = find_exactly_one_t::valueForAssignment; static_assert(value != -1); - static_print(); __union_helper::set(std::forward(t), std::in_place_index, this->data_); return *this; } From f813c228da3f7a43f68bf04220de88c95e0a6ca0 Mon Sep 17 00:00:00 2001 From: ChrisBenua Date: Sat, 6 Mar 2021 14:42:36 +0300 Subject: [PATCH 7/7] enhancement2 --- module-1/homework/Variant/variant.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module-1/homework/Variant/variant.h b/module-1/homework/Variant/variant.h index 6a65c7e2..1ed7fc30 100644 --- a/module-1/homework/Variant/variant.h +++ b/module-1/homework/Variant/variant.h @@ -5,7 +5,7 @@ template auto test_implicitly_convertible(int) -> decltype( -void(std::declval()(std::declval())), std::true_type{} + void(std::declval()(std::declval())), std::true_type{} ); template