Quellcode durchsuchen

refactor: use a recursive template for defining ObjectAdapter

Sam Jaffe vor 2 Wochen
Ursprung
Commit
ba954291ba

+ 1 - 1
include/jvalidate/detail/reference_manager.h

@@ -460,7 +460,7 @@ private:
    * - All of the enabled keywords in the vocabulary
    * - The list of enabled vocabulary metaschema (used for is_format_assertion)
    */
-  auto extract_keywords(ObjectAdapter auto const & vocabularies) const
+  auto extract_keywords(ObjectAdapter<A> auto const & vocabularies) const
       -> std::pair<std::unordered_map<std::string, bool>, std::unordered_set<std::string>> {
     std::unordered_map<std::string, bool> keywords;
     std::unordered_set<std::string> vocab_docs;

+ 1 - 2
include/jvalidate/detail/simple_adapter.h

@@ -131,8 +131,7 @@ private:
  */
 template <typename JSON, typename CRTP = AdapterFor<JSON>> class SimpleAdapter : public Adapter {
 public:
-  static constexpr bool is_mutable =
-      not std::is_const_v<JSON> && MutableObject<decltype(std::declval<CRTP>().as_object())>;
+  static constexpr bool is_mutable = not std::is_const_v<JSON> && HasMutableObject<CRTP>;
   using value_type = std::remove_const_t<JSON>;
 
 public:

+ 12 - 9
include/jvalidate/forward.h

@@ -103,19 +103,19 @@ concept ObjectIterator =
       { it->second } -> std::convertible_to<adapter::Adapter const &>;
     };
 
-template <typename A>
+template <typename A, typename Reentrant>
 concept ArrayAdapter = requires(A const a) {
   { a.size() } -> std::convertible_to<std::size_t>;
-  { a[0UL] } -> std::convertible_to<adapter::Adapter const &>;
+  { a[0UL] } -> std::same_as<Reentrant>;
   { a.begin() } -> ArrayIterator;
   { a.end() } -> ArrayIterator;
 };
 
-template <typename A>
+template <typename A, typename Reentrant>
 concept ObjectAdapter = requires(A const a) {
   { a.size() } -> std::convertible_to<std::size_t>;
   { a.contains("") } -> std::same_as<bool>;
-  { a[""] } -> std::convertible_to<adapter::Adapter const &>;
+  { a[""] } -> std::same_as<Reentrant>;
   { a.begin() } -> ObjectIterator;
   { a.end() } -> ObjectIterator;
 };
@@ -138,18 +138,21 @@ concept Adapter = std::is_base_of_v<adapter::Adapter, A> && requires(A const a)
   { a.as_integer() } -> std::convertible_to<int64_t>;
   { a.as_number() } -> std::convertible_to<double>;
   { a.as_number() } -> std::floating_point;
-  { a.as_object() } -> ObjectAdapter;
-  { a.as_array() } -> ArrayAdapter;
+  { a.as_object() } -> ObjectAdapter<A>;
+  { a.as_array() } -> ArrayAdapter<A>;
 
   { a.array_size() } -> std::convertible_to<size_t>;
   { a.object_size() } -> std::convertible_to<size_t>;
 };
 
-template <typename A>
-concept MutableObject = ObjectAdapter<A> && requires(A const a) {
+template <typename A, typename Reentrant>
+concept MutableObject = ObjectAdapter<A, Reentrant> && requires(A const a) {
   { a.assign("", std::declval<adapter::Const>()) };
 };
 
+template <typename A>
+concept HasMutableObject = MutableObject<decltype(std::declval<A>().as_object()), A>;
+
 /**
  * @brief An extension of Adapter that is capable of altering the underlying
  * JSON node. In general, that means that a non-const ref is captured when
@@ -163,7 +166,7 @@ template <typename A>
 concept MutableAdapter = Adapter<A> && requires(A const a) {
   { a.assign(std::declval<adapter::Const>()) };
   { a.assign(std::declval<adapter::Adapter>()) };
-  { a.as_object() } -> MutableObject;
+  { a.as_object() } -> MutableObject<A>;
 };
 
 template <typename R>