Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion cpp/Platform.Interfaces/CDictionary.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,68 @@ namespace Platform::Interfaces {

return false;
}

template <typename TRawSelf, typename... TArgs>
consteval bool CReadonlyDictionaryHelpFunction() {
using Self = TRawSelf;

using GenericKey = std::remove_reference_t<decltype(std::get<0>(std::declval<typename Enumerable<Self>::Item>()))>;
using GenericValue = std::remove_reference_t<decltype(std::get<1>(std::declval<typename Enumerable<Self>::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<bool>;
{ self.empty() } -> std::same_as<bool>;
{ self.size() } -> std::integral;

requires std::ranges::forward_range<const Self>;
};
}
if constexpr (sizeof...(TArgs) == 1) {
return requires(const Self self, std::tuple<TArgs...> args,
decltype(std::get<0>(args)) key) {
{ self.find(key) } -> std::forward_iterator;
{ self.contains(key) } -> std::same_as<bool>;
{ self.empty() } -> std::same_as<bool>;
{ self.size() } -> std::integral;

requires std::ranges::forward_range<const Self>;
};
}
if constexpr (sizeof...(TArgs) == 2) {
return requires(const Self self, std::tuple<TArgs...> args,
decltype(std::get<0>(args)) key) {
{ self.find(key) } -> std::forward_iterator;
{ self.contains(key) } -> std::same_as<bool>;
{ self.empty() } -> std::same_as<bool>;
{ self.size() } -> std::integral;

requires std::ranges::forward_range<const Self>;
};
}

return false;
}
} // namespace Internal

template <typename TSelf, typename... TArgs>
concept CDictionary = CEnumerable<TSelf> && Internal::CDictionaryHelpFunction<TSelf, TArgs...>();

template <typename TSelf, typename... TArgs>
concept CReadonlyDictionary = CEnumerable<TSelf> && Internal::CReadonlyDictionaryHelpFunction<TSelf, TArgs...>();

template <CDictionary TSelf>
struct Dictionary : Enumerable<TSelf> {
using base = Enumerable<TSelf>;
using Key = decltype(std::get<0>(std::declval<base::Item>()));
using Value = decltype(std::get<1>(std::declval<base::Item>()));
};
} // namespace Platform::Interfaces

template <CReadonlyDictionary TSelf>
struct ReadonlyDictionary : Enumerable<TSelf> {
using base = Enumerable<TSelf>;
using Key = decltype(std::get<0>(std::declval<base::Item>()));
using Value = decltype(std::get<1>(std::declval<base::Item>()));
};
} // namespace Platform::Interfaces
34 changes: 33 additions & 1 deletion cpp/Platform.Interfaces/CList.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,43 @@ namespace Platform::Interfaces {

return false;
}

template <typename TRawSelf, typename... TItems>
consteval bool CReadonlyListHelpFunction() {
using Self = TRawSelf;

if constexpr (sizeof...(TItems) == 1) {
return requires(const Self self, std::size_t index, std::tuple<TItems...> items, decltype(std::get<0>(items)) item, std::ranges::iterator_t<const Self> const_iterator) {
{ self.size() } -> std::integral;
{ self.empty() } -> std::same_as<bool>;
{ self[index] } -> std::convertible_to<decltype(item)>;

requires std::ranges::forward_range<const Self>;
};
}
if constexpr (sizeof...(TItems) == 0) {
return requires(const Self self, std::size_t index, typename Enumerable<const Self>::Item generic_item, typename Enumerable<const Self>::Iter const_iterator) {
{ self.size() } -> std::integral;
{ self.empty() } -> std::same_as<bool>;
{ self[index] } -> std::convertible_to<decltype(generic_item)>;

requires std::ranges::forward_range<const Self>;
};
}

return false;
}
} // namespace Internal

template <typename TSelf, typename... TItems>
concept CList = CArray<TSelf> && Internal::CListHelpFunction<TSelf, TItems...>();

template <typename TSelf, typename... TItems>
concept CReadonlyList = CArray<TSelf> && Internal::CReadonlyListHelpFunction<TSelf, TItems...>();

template <CList TSelf>
struct List : Enumerable<TSelf> {};
} // namespace Platform::Interfaces

template <CReadonlyList TSelf>
struct ReadonlyList : Enumerable<TSelf> {};
} // namespace Platform::Interfaces
36 changes: 35 additions & 1 deletion cpp/Platform.Interfaces/CSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,45 @@ namespace Platform::Interfaces {
return false;
}

template <typename TRawSelf, typename... TItems>
consteval bool CReadonlySetHelpFunction() {
using Self = TRawSelf;

if constexpr (sizeof...(TItems) == 1) {
return requires(const Self self, std::tuple<TItems...> items, decltype(std::get<0>(items)) item) {
{ self.find(item) } -> std::same_as<std::ranges::iterator_t<const Self>>;
{ self.contains(item) } -> std::same_as<bool>;
{ self.empty() } -> std::same_as<bool>;
{ self.size() } -> std::integral;

requires std::ranges::forward_range<const Self>;
};
}
if constexpr (sizeof...(TItems) == 0) {
return requires(const Self self, typename Enumerable<const Self>::Item generic_item) {
{ self.find(generic_item) } -> std::same_as<std::ranges::iterator_t<const Self>>;
{ self.contains(generic_item) } -> std::same_as<bool>;
{ self.empty() } -> std::same_as<bool>;
{ self.size() } -> std::integral;

requires std::ranges::forward_range<const Self>;
};
}

return false;
}

} // namespace Internal

template <typename TSelf, typename... TItems>
concept CSet = CEnumerable<TSelf> && Internal::CSetHelpFunction<TSelf, TItems...>();

template <typename TSelf, typename... TItems>
concept CReadonlySet = CEnumerable<TSelf> && Internal::CReadonlySetHelpFunction<TSelf, TItems...>();

template <CSet TSelf>
struct Set : Enumerable<TSelf> {};
} // namespace Platform::Interfaces

template <CReadonlySet TSelf>
struct ReadonlySet : Enumerable<TSelf> {};
} // namespace Platform::Interfaces
Binary file added examples/test_readonly_concepts
Binary file not shown.
53 changes: 53 additions & 0 deletions examples/test_readonly_concepts.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "../cpp/Platform.Interfaces/CDictionary.h"
#include "../cpp/Platform.Interfaces/CList.h"
#include "../cpp/Platform.Interfaces/CSet.h"
#include <map>
#include <vector>
#include <set>
#include <iostream>

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<int, std::string> const_map = {{1, "one"}, {2, "two"}};

// This should work with CReadonlyDictionary
static_assert(CReadonlyDictionary<const std::map<int, std::string>>);

// Test with const std::vector
const std::vector<int> const_vec = {1, 2, 3};

// This should work with CReadonlyList
static_assert(CReadonlyList<const std::vector<int>>);

// Test with const std::set
const std::set<int> const_set = {1, 2, 3};

// This should work with CReadonlySet
static_assert(CReadonlySet<const std::set<int>>);

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<int, std::string> mutable_map;
std::vector<int> mutable_vec;
std::set<int> mutable_set;

// These should work with regular concepts
static_assert(CDictionary<std::map<int, std::string>>);
static_assert(CList<std::vector<int>>);
static_assert(CSet<std::set<int>>);

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;
}
Loading