diff --git a/cpp/Platform.Interfaces.Tests/Platform.Interfaces.Tests.cpp b/cpp/Platform.Interfaces.Tests/Platform.Interfaces.Tests.cpp index e94e7fd3..745edc68 100644 --- a/cpp/Platform.Interfaces.Tests/Platform.Interfaces.Tests.cpp +++ b/cpp/Platform.Interfaces.Tests/Platform.Interfaces.Tests.cpp @@ -2,6 +2,57 @@ #include namespace Platform::Interfaces::Tests { + namespace { + struct ReadonlyListModel { + int items[1]{}; + + const int* begin() const { return items; } + const int* end() const { return items + 1; } + const int& operator[](std::size_t index) const { return items[index]; } + std::size_t size() const { return static_cast(end() - begin()); } + bool empty() const { return begin() == end(); } + }; + + struct ReadonlySetModel { + int items[1]{}; + + const int* begin() const { return items; } + const int* end() const { return items + 1; } + const int* find(int item) const { return items[0] == item ? begin() : end(); } + bool contains(int item) const { return find(item) != end(); } + std::size_t size() const { return static_cast(end() - begin()); } + bool empty() const { return begin() == end(); } + }; + + struct ReadonlyDictionaryModel { + std::tuple items[1]{}; + + const std::tuple* begin() const { return items; } + const std::tuple* end() const { return items + 1; } + const std::tuple* find(int key) const { return std::get<0>(items[0]) == key ? begin() : end(); } + bool contains(int key) const { return find(key) != end(); } + std::size_t size() const { return static_cast(end() - begin()); } + bool empty() const { return begin() == end(); } + }; + } // namespace + + static_assert(CReadonlyList); + static_assert(CReadonlyList); + static_assert(!CList); + static_assert(std::same_as::Item, int>); + + static_assert(CReadonlySet); + static_assert(CReadonlySet); + static_assert(!CSet); + static_assert(std::same_as::Item, int>); + + static_assert(CReadonlyDictionary); + static_assert(CReadonlyDictionary); + static_assert(CReadonlyDictionary); + static_assert(!CDictionary); + static_assert(std::same_as::Key>, int>); + static_assert(std::same_as::Value>, int>); + TEST(CompileTests, Counter) { struct EmptyCounter1 : ICounter { int Count() { return {}; } diff --git a/cpp/Platform.Interfaces/CDictionary.h b/cpp/Platform.Interfaces/CDictionary.h index ba2857b3..25f8cffa 100644 --- a/cpp/Platform.Interfaces/CDictionary.h +++ b/cpp/Platform.Interfaces/CDictionary.h @@ -64,15 +64,67 @@ namespace Platform::Interfaces { return false; } + + template + consteval bool CReadonlyDictionaryHelpFunction() { + using Self = TRawSelf; + + using GenericKey = std::remove_reference_t(std::declval::Item>()))>; + + if constexpr (sizeof...(TArgs) == 0) { + return requires(const Self& self, GenericKey generic_key) { + { self.find(generic_key) } -> std::forward_iterator; + { self.contains(generic_key) } -> std::same_as; + { self.empty() } -> std::same_as; + { self.size() } -> std::integral; + + requires std::ranges::forward_range; + }; + } + if constexpr (sizeof...(TArgs) == 1) { + return requires(const Self& self, std::tuple args, + decltype(std::get<0>(args)) key) { + { self.find(key) } -> std::forward_iterator; + { self.contains(key) } -> std::same_as; + { self.empty() } -> std::same_as; + { self.size() } -> std::integral; + + requires std::ranges::forward_range; + }; + } + if constexpr (sizeof...(TArgs) == 2) { + return requires(const Self& self, std::tuple args, + decltype(std::get<0>(args)) key) { + { self.find(key) } -> std::forward_iterator; + { self.contains(key) } -> std::same_as; + { self.empty() } -> std::same_as; + { self.size() } -> std::integral; + + requires std::ranges::forward_range; + }; + } + + return false; + } } // namespace Internal template concept CDictionary = CEnumerable && Internal::CDictionaryHelpFunction(); + template + concept CReadonlyDictionary = CEnumerable && Internal::CReadonlyDictionaryHelpFunction(); + template struct Dictionary : Enumerable { using base = Enumerable; - using Key = decltype(std::get<0>(std::declval())); - using Value = decltype(std::get<1>(std::declval())); + using Key = decltype(std::get<0>(std::declval())); + using Value = decltype(std::get<1>(std::declval())); + }; + + template + struct ReadonlyDictionary : Enumerable { + using base = Enumerable; + using Key = decltype(std::get<0>(std::declval())); + using Value = decltype(std::get<1>(std::declval())); }; } // namespace Platform::Interfaces diff --git a/cpp/Platform.Interfaces/CList.h b/cpp/Platform.Interfaces/CList.h index a4ab17ac..b1dfb6c2 100644 --- a/cpp/Platform.Interfaces/CList.h +++ b/cpp/Platform.Interfaces/CList.h @@ -36,11 +36,47 @@ namespace Platform::Interfaces { return false; } + + template + consteval bool CReadonlyListHelpFunction() { + using Self = TRawSelf; + + if constexpr (sizeof...(TItems) == 1) { + using RequiredItem = std::remove_reference_t(std::declval>()))>; + + return requires(const Self& self, std::size_t index) { + { self.size() } -> std::integral; + { self.empty() } -> std::same_as; + { self[index] } -> std::convertible_to; + + requires std::ranges::forward_range; + }; + } + if constexpr (sizeof...(TItems) == 0) { + using GenericItem = typename Enumerable::Item; + + return requires(const Self& self, std::size_t index) { + { self.size() } -> std::integral; + { self.empty() } -> std::same_as; + { self[index] } -> std::convertible_to; + + requires std::ranges::forward_range; + }; + } + + return false; + } } // namespace Internal template concept CList = CArray && Internal::CListHelpFunction(); + template + concept CReadonlyList = CArray && Internal::CReadonlyListHelpFunction(); + template struct List : Enumerable {}; + + template + struct ReadonlyList : Enumerable {}; } // namespace Platform::Interfaces diff --git a/cpp/Platform.Interfaces/CSet.h b/cpp/Platform.Interfaces/CSet.h index 7f9bceb8..b61e4365 100644 --- a/cpp/Platform.Interfaces/CSet.h +++ b/cpp/Platform.Interfaces/CSet.h @@ -43,11 +43,45 @@ namespace Platform::Interfaces { return false; } + template + consteval bool CReadonlySetHelpFunction() { + using Self = TRawSelf; + + if constexpr (sizeof...(TItems) == 1) { + return requires(const Self& self, std::tuple items, decltype(std::get<0>(items)) item) { + { self.find(item) } -> std::same_as>; + { self.contains(item) } -> std::same_as; + { self.empty() } -> std::same_as; + { self.size() } -> std::integral; + + requires std::ranges::forward_range; + }; + } + if constexpr (sizeof...(TItems) == 0) { + return requires(const Self& self, typename Enumerable::Item generic_item) { + { self.find(generic_item) } -> std::same_as>; + { self.contains(generic_item) } -> std::same_as; + { self.empty() } -> std::same_as; + { self.size() } -> std::integral; + + requires std::ranges::forward_range; + }; + } + + return false; + } + } // namespace Internal template concept CSet = CEnumerable && Internal::CSetHelpFunction(); + template + concept CReadonlySet = CEnumerable && Internal::CReadonlySetHelpFunction(); + template struct Set : Enumerable {}; + + template + struct ReadonlySet : Enumerable {}; } // namespace Platform::Interfaces diff --git a/cpp/Platform.Interfaces/Platform.Interfaces.TemplateLibrary.nuspec b/cpp/Platform.Interfaces/Platform.Interfaces.TemplateLibrary.nuspec index ac432092..ac877563 100644 --- a/cpp/Platform.Interfaces/Platform.Interfaces.TemplateLibrary.nuspec +++ b/cpp/Platform.Interfaces/Platform.Interfaces.TemplateLibrary.nuspec @@ -6,7 +6,7 @@ LinksPlatform's Platform.Interfaces is a Template Library what contains common concepts templates. LinksPlatform's Platform.Interfaces is a Template Library what contains set of C++ concepts templates. Use Platform.Interfaces.h file to include the library. Test release for automatic deploy system. - 0.3.42 + 0.3.43 konard, uselessgoddess, Mitron57 konard, uselessgoddess, Mitron57 konard, uselessgoddess, Mitron57