diff --git a/cpp/Platform.Interfaces/CDictionary.h b/cpp/Platform.Interfaces/CDictionary.h index ba2857b..8faa1e9 100644 --- a/cpp/Platform.Interfaces/CDictionary.h +++ b/cpp/Platform.Interfaces/CDictionary.h @@ -64,15 +64,68 @@ namespace Platform::Interfaces { return false; } + + template + consteval bool CReadonlyDictionaryHelpFunction() { + using Self = TRawSelf; + + using GenericKey = std::remove_reference_t(std::declval::Item>()))>; + using GenericValue = 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())); }; -} // namespace Platform::Interfaces + + 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 \ No newline at end of file diff --git a/cpp/Platform.Interfaces/CList.h b/cpp/Platform.Interfaces/CList.h index a4ab17a..2fb9201 100644 --- a/cpp/Platform.Interfaces/CList.h +++ b/cpp/Platform.Interfaces/CList.h @@ -36,11 +36,43 @@ namespace Platform::Interfaces { return false; } + + template + consteval bool CReadonlyListHelpFunction() { + using Self = TRawSelf; + + if constexpr (sizeof...(TItems) == 1) { + return requires(const Self self, std::size_t index, std::tuple items, decltype(std::get<0>(items)) item, std::ranges::iterator_t const_iterator) { + { self.size() } -> std::integral; + { self.empty() } -> std::same_as; + { self[index] } -> std::convertible_to; + + requires std::ranges::forward_range; + }; + } + if constexpr (sizeof...(TItems) == 0) { + return requires(const Self self, std::size_t index, typename Enumerable::Item generic_item, typename Enumerable::Iter const_iterator) { + { 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 {}; -} // namespace Platform::Interfaces + + template + struct ReadonlyList : Enumerable {}; +} // namespace Platform::Interfaces \ No newline at end of file diff --git a/cpp/Platform.Interfaces/CSet.h b/cpp/Platform.Interfaces/CSet.h index 7f9bceb..781d6f5 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 {}; -} // namespace Platform::Interfaces + + template + struct ReadonlySet : Enumerable {}; +} // namespace Platform::Interfaces \ No newline at end of file diff --git a/examples/test_readonly_concepts b/examples/test_readonly_concepts new file mode 100755 index 0000000..b5bd049 Binary files /dev/null and b/examples/test_readonly_concepts differ diff --git a/examples/test_readonly_concepts.cpp b/examples/test_readonly_concepts.cpp new file mode 100644 index 0000000..3b8339d --- /dev/null +++ b/examples/test_readonly_concepts.cpp @@ -0,0 +1,53 @@ +#include "../cpp/Platform.Interfaces/CDictionary.h" +#include "../cpp/Platform.Interfaces/CList.h" +#include "../cpp/Platform.Interfaces/CSet.h" +#include +#include +#include +#include + +using namespace Platform::Interfaces; + +// Test that const qualified types work with readonly concepts +void test_readonly_concepts() { + // Test with const std::map + const std::map const_map = {{1, "one"}, {2, "two"}}; + + // This should work with CReadonlyDictionary + static_assert(CReadonlyDictionary>); + + // Test with const std::vector + const std::vector const_vec = {1, 2, 3}; + + // This should work with CReadonlyList + static_assert(CReadonlyList>); + + // Test with const std::set + const std::set const_set = {1, 2, 3}; + + // This should work with CReadonlySet + static_assert(CReadonlySet>); + + std::cout << "All readonly concept tests passed!" << std::endl; +} + +// Test that regular concepts still work with non-const types +void test_mutable_concepts() { + std::map mutable_map; + std::vector mutable_vec; + std::set mutable_set; + + // These should work with regular concepts + static_assert(CDictionary>); + static_assert(CList>); + static_assert(CSet>); + + std::cout << "All mutable concept tests passed!" << std::endl; +} + +int main() { + test_readonly_concepts(); + test_mutable_concepts(); + std::cout << "All tests completed successfully!" << std::endl; + return 0; +} \ No newline at end of file