diff --git a/include/oi/IntrospectionResult-inl.h b/include/oi/IntrospectionResult-inl.h index 13928b5..a0866a7 100644 --- a/include/oi/IntrospectionResult-inl.h +++ b/include/oi/IntrospectionResult-inl.h @@ -45,7 +45,9 @@ inline IntrospectionResult::const_iterator IntrospectionResult::begin() const { return cbegin(); } inline IntrospectionResult::const_iterator IntrospectionResult::cbegin() const { - return ++const_iterator{buf_.cbegin(), inst_}; + auto it = const_iterator{buf_.cbegin(), inst_}; + ++it; + return it; } inline IntrospectionResult::const_iterator IntrospectionResult::end() const { return cend(); @@ -70,6 +72,18 @@ inline const result::Element* IntrospectionResult::const_iterator::operator->() return &*next_; } +inline IntrospectionResult::const_iterator +IntrospectionResult::const_iterator::clone() const { + auto ret{*this}; + + // Fix the self referential type_path_ field in next_ + if (ret.next_.has_value()) { + ret.next_->type_path = ret.type_path_; + } + + return ret; +} + inline bool IntrospectionResult::const_iterator::operator==( const IntrospectionResult::const_iterator& that) const { // Case 1: The next data to read differs, thus the iterators are different. diff --git a/include/oi/IntrospectionResult.h b/include/oi/IntrospectionResult.h index 091028f..1675423 100644 --- a/include/oi/IntrospectionResult.h +++ b/include/oi/IntrospectionResult.h @@ -43,6 +43,16 @@ class IntrospectionResult { const_iterator& operator++(); const_iterator operator++(int); + private: + const_iterator(const const_iterator&) = default; + const_iterator& operator=(const const_iterator& other) = default; + + public: + const_iterator(const_iterator&&) = default; + const_iterator& operator=(const_iterator&&) = default; + // Explicit interface for copying + const_iterator clone() const; + private: using stack_t = std::stack>; diff --git a/include/oi/result/Element.h b/include/oi/result/Element.h index c971236..4a47233 100644 --- a/include/oi/result/Element.h +++ b/include/oi/result/Element.h @@ -41,8 +41,7 @@ struct Element { }; std::string_view name; - std::vector - type_path; // TODO: should be span + std::span type_path; std::span type_names; size_t static_size; size_t exclusive_size; diff --git a/include/oi/result/SizedResult-inl.h b/include/oi/result/SizedResult-inl.h index f86ff0c..94418a4 100644 --- a/include/oi/result/SizedResult-inl.h +++ b/include/oi/result/SizedResult-inl.h @@ -35,7 +35,9 @@ SizedResult::SizedResult(Res res) : res_{std::move(res)} { template typename SizedResult::const_iterator SizedResult::begin() const { - return ++const_iterator{res_.begin(), res_.end()}; + const_iterator it{res_.begin(), res_.end()}; + ++it; + return it; } template typename SizedResult::const_iterator SizedResult::end() const { @@ -44,7 +46,7 @@ typename SizedResult::const_iterator SizedResult::end() const { template SizedResult::const_iterator::const_iterator(It it, const It& end) - : data_{it} { + : data_{it.clone()} { struct StackEntry { size_t index; size_t depth; @@ -75,7 +77,8 @@ SizedResult::const_iterator::const_iterator(It it, const It& end) } template -SizedResult::const_iterator::const_iterator(It end) : data_{end} { +SizedResult::const_iterator::const_iterator(It end) + : data_{std::move(end)} { } template diff --git a/oi/IntrospectionResult.cpp b/oi/IntrospectionResult.cpp index 5310001..4b4839d 100644 --- a/oi/IntrospectionResult.cpp +++ b/oi/IntrospectionResult.cpp @@ -70,7 +70,7 @@ IntrospectionResult::const_iterator::operator++() { if constexpr (std::is_same_v) { type_path_.emplace_back(ty.name); stack_.emplace(exporters::inst::PopTypePath{}); - next_ = result::Element{ + next_.emplace(result::Element{ .name = ty.name, .type_path = type_path_, .type_names = ty.type_names, @@ -79,7 +79,7 @@ IntrospectionResult::const_iterator::operator++() { .container_stats = std::nullopt, .is_set_stats = std::nullopt, .is_primitive = ty.is_primitive, - }; + }); for (const auto& [dy, handler] : ty.processors) { auto parsed = exporters::ParsedData::parse(data_, dy); @@ -94,7 +94,6 @@ IntrospectionResult::const_iterator::operator++() { .second; type_path_.back() = new_name_ref; - next_->type_path.back() = new_name_ref; next_->name = new_name_ref; }