Nui
observed_value.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <iterator>
4 #include <nui/concepts.hpp>
7 #include <nui/utility/assert.hpp>
10 
11 #include <memory>
12 #include <vector>
13 #include <functional>
14 #include <type_traits>
15 #include <list>
16 #include <utility>
17 #include <deque>
18 #include <string>
19 #include <cassert>
20 #include <set>
21 #include <memory>
22 
23 namespace Nui
24 {
26  {};
28 
30  {
31  public:
33  : eventContext_{ctx}
34  , attachedEvents_{}
36  {}
37  virtual ~ObservedBase() = default;
38  ObservedBase(ObservedBase const&) = delete;
41  , attachedEvents_{}
43  {
44  // events are outside the value logic of the observed class. the contained value is moved, but the events
45  // are merged.
46  for (auto& event : other.attachedEvents_)
47  attachedEvents_.push_back(std::move(event));
48  for (auto& event : other.attachedOneshotEvents_)
49  attachedOneshotEvents_.push_back(std::move(event));
50  }
51  ObservedBase& operator=(ObservedBase const&) = delete;
53  {
54  eventContext_ = other.eventContext_;
55  for (auto& event : other.attachedEvents_)
56  attachedEvents_.push_back(std::move(event));
57  for (auto& event : other.attachedOneshotEvents_)
58  attachedOneshotEvents_.push_back(std::move(event));
59  return *this;
60  }
61 
63  {
64  attachedEvents_.emplace_back(eventId);
65  }
67  {
68  attachedOneshotEvents_.emplace_back(eventId);
69  }
71  {
72  attachedEvents_.erase(
73  std::remove(std::begin(attachedEvents_), std::end(attachedEvents_), eventId),
74  std::end(attachedEvents_));
75  }
76 
77  std::size_t attachedEventCount() const
78  {
79  return attachedEvents_.size();
80  }
81  std::size_t attachedOneshotEventCount() const
82  {
83  return attachedOneshotEvents_.size();
84  }
85  std::size_t totalAttachedEventCount() const
86  {
87  return attachedEvents_.size() + attachedOneshotEvents_.size();
88  }
89 
94  {
95  attachedEvents_.clear();
96  attachedOneshotEvents_.clear();
97  }
98 
99  virtual void update(bool /*force*/ = false) const
100  {
101  NUI_ASSERT(eventContext_ != nullptr, "Event context must never be null.");
102 
103  for (auto& event : attachedEvents_)
104  {
105  auto activationResult = eventContext_->activateEvent(event);
106  if (activationResult.found == false)
108  }
109  for (auto& event : attachedOneshotEvents_)
111  attachedOneshotEvents_.clear();
112  attachedEvents_.erase(
113  std::remove(std::begin(attachedEvents_), std::end(attachedEvents_), EventRegistry::invalidEventId),
114  std::end(attachedEvents_));
115  }
116 
117  void updateNow(bool force = false) const
118  {
119  NUI_ASSERT(eventContext_ != nullptr, "Event context must never be null.");
120 
121  update(force);
123  }
124 
125  protected:
127  mutable std::vector<EventContext::EventIdType> attachedEvents_;
128  mutable std::vector<EventContext::EventIdType> attachedOneshotEvents_;
129  };
130 
131  template <typename ContainedT>
133  {
134  public:
135  using value_type = ContainedT;
136 
137  public:
139  {
140  public:
142  : observed_{observed}
143  , now_{false}
144  {}
145  explicit ModificationProxy(ModifiableObserved& observed, bool now)
146  : observed_{observed}
147  , now_{now}
148  {}
150  {
151  try
152  {
153  if (now_)
154  observed_.updateNow(true);
155  else
156  observed_.update(true);
157  }
158  catch (...)
159  {
160  // TODO: log?
161  }
162  }
163  auto& value()
164  {
165  return observed_.contained_;
166  }
167  auto* operator->()
168  {
169  return &observed_.contained_;
170  }
171  auto& operator*()
172  {
173  return observed_.contained_;
174  }
175  operator ContainedT&()
176  {
177  return observed_.contained_;
178  }
179 
180  private:
181  ModifiableObserved& observed_;
182  bool now_;
183  };
184 
185  public:
188  , contained_{}
189  {}
192  : ObservedBase{std::move(other)}
193  , contained_{std::move(other.contained_)}
194  {
195  update();
196  };
199  {
200  if (this != &other)
201  {
202  ObservedBase::operator=(std::move(other));
203  contained_ = std::move(other.contained_);
204  update();
205  }
206  return *this;
207  };
208  ModifiableObserved& operator=(ContainedT const& contained)
209  {
210  contained_ = contained;
211  update();
212  return *this;
213  }
214  ModifiableObserved& operator=(ContainedT&& contained)
215  {
216  contained_ = std::move(contained);
217  update();
218  return *this;
219  }
220  ~ModifiableObserved() = default;
221 
222  template <typename T = ContainedT>
223  explicit ModifiableObserved(T&& t)
225  , contained_{std::forward<T>(t)}
226  {}
227 
230  , contained_{}
231  {}
232 
233  template <typename T = ContainedT>
236  , contained_{std::forward<T>(t)}
237  {}
238 
245  template <typename T = ContainedT>
247  {
248  contained_ = std::forward<T>(t);
249  update();
250  return *this;
251  }
252 
253  template <typename T = ContainedT, typename U>
254  requires PlusAssignable<T, U>
256  {
257  this->contained_ += rhs;
258  return *this;
259  }
260  template <typename T = ContainedT, typename U>
261  requires MinusAssignable<T, U>
263  {
264  this->contained_ -= rhs;
265  return *this;
266  }
267 
268  template <typename T = ContainedT>
269  requires std::equality_comparable_with<ContainedT, T> && Fundamental<T> && Fundamental<ContainedT>
271  {
272  return assignChecked(t);
273  }
274 
275  template <typename T = ContainedT>
276  requires std::equality_comparable_with<ContainedT, T>
278  {
279  if (contained_ != other)
280  {
281  contained_ = std::forward<T>(other);
282  update();
283  }
284  return *this;
285  }
286 
294  {
295  return ModificationProxy{*this};
296  }
297 
299  {
300  return ModificationProxy{*this, true};
301  }
302 
303  explicit operator bool() const
304  requires std::convertible_to<ContainedT, bool>
305  {
306  return static_cast<bool>(contained_);
307  }
308 
309  ContainedT& value()
310  {
311  return contained_;
312  }
313  ContainedT const& value() const
314  {
315  return contained_;
316  }
317  ContainedT& operator*()
318  {
319  return contained_;
320  }
321  ContainedT const& operator*() const
322  {
323  return contained_;
324  }
325  ContainedT* operator->()
326  {
327  return &contained_;
328  }
329  ContainedT const* operator->() const
330  {
331  return &contained_;
332  }
333 
337  void assignWithoutUpdate(ContainedT&& t)
338  {
339  contained_ = std::forward<ContainedT>(t);
340  }
341 
342  protected:
343  ContainedT contained_;
344  };
345 
346  template <typename ContainerT>
347  class ObservedContainer;
348 
349  namespace ContainerWrapUtility
350  {
351  template <typename T, typename ContainerT>
353  {
354  public:
355  ReferenceWrapper(ObservedContainer<ContainerT>* owner, std::size_t pos, T& ref)
356  : owner_{owner}
357  , pos_{pos}
358  , ref_{&ref}
359  {}
362  : owner_{other.owner_}
363  , pos_{other.pos_}
364  , ref_{other.ref_}
365  {
366  other.owner_ = nullptr;
367  other.pos_ = 0;
368  other.ref_ = nullptr;
369  }
372  {
373  if (this != &other)
374  {
375  owner_ = other.owner_;
376  pos_ = other.pos_;
377  ref_ = other.ref_;
378  other.owner_ = nullptr;
379  other.pos_ = 0;
380  other.ref_ = nullptr;
381  }
382  return *this;
383  }
384  operator T&()
385  {
386  return *ref_;
387  }
389  {
390  owner_->insertRangeChecked(pos_, pos_, RangeOperationType::Modify);
391  return *ref_;
392  }
393  T const& operator*() const
394  {
395  return *ref_;
396  }
398  {
399  owner_->insertRangeChecked(pos_, pos_, RangeOperationType::Modify);
400  return ref_;
401  }
402  T const* operator->() const
403  {
404  return ref_;
405  }
406  T& get()
407  {
408  owner_->insertRangeChecked(pos_, pos_, RangeOperationType::Modify);
409  return *ref_;
410  }
411  T const& getReadonly()
412  {
413  return *ref_;
414  }
415  void operator=(T&& val)
416  {
417  *ref_ = std::move(val);
418  owner_->insertRangeChecked(pos_, pos_, RangeOperationType::Modify);
419  }
420  void operator=(T const& val)
421  {
422  *ref_ = val;
423  owner_->insertRangeChecked(pos_, pos_, RangeOperationType::Modify);
424  }
425 
426  protected:
428  std::size_t pos_;
429  T* ref_;
430  };
431 
432  template <typename T, typename ContainerT>
434  {
435  return wrapper.get();
436  }
437  template <typename T, typename ContainerT>
439  {
440  return wrapper.get();
441  }
442  auto& unwrapReferenceWrapper(auto& ref)
443  {
444  return ref;
445  }
446  auto const& unwrapReferenceWrapper(auto const& ref)
447  {
448  return ref;
449  }
450 
451  template <typename T, typename ContainerT>
453  {
454  public:
455  PointerWrapper(ObservedContainer<ContainerT>* owner, std::size_t pos, T* ptr) noexcept
456  : owner_{owner}
457  , pos_{pos}
458  , ptr_{ptr}
459  {}
460  operator T&()
461  {
462  return *ptr_;
463  }
465  {
466  owner_->insertRangeChecked(pos_, pos_, RangeOperationType::Modify);
467  return *ptr_;
468  }
469  T const& operator*() const
470  {
471  return *ptr_;
472  }
474  {
475  owner_->insertRangeChecked(pos_, pos_, RangeOperationType::Modify);
476  return ptr_;
477  }
478  T const* operator->() const
479  {
480  return ptr_;
481  }
482  T& get()
483  {
484  owner_->insertRangeChecked(pos_, pos_, RangeOperationType::Modify);
485  return *ptr_;
486  }
487  T const& getReadonly()
488  {
489  return *ptr_;
490  }
491  void operator=(T* ptr)
492  {
493  ptr_ = ptr;
494  owner_->insertRangeChecked(pos_, pos_, RangeOperationType::Modify);
495  }
496 
497  protected:
499  std::size_t pos_;
500  T* ptr_;
501  };
502 
503  template <typename WrappedIterator, typename ContainerT>
505  {
506  public:
507  using iterator_category = std::random_access_iterator_tag;
508  using value_type = typename WrappedIterator::value_type;
509  using difference_type = typename WrappedIterator::difference_type;
512 
513  public:
514  IteratorWrapper(ObservedContainer<ContainerT>* owner, WrappedIterator it)
515  : owner_{owner}
516  , it_{std::move(it)}
517  {}
518  IteratorWrapper(IteratorWrapper const&) = default;
523  {
524  it_ += n;
525  return *this;
526  }
528  {
529  it_ -= n;
530  return *this;
531  }
533  {
534  ++it_;
535  return *this;
536  }
538  {
539  return IteratorWrapper{it_++};
540  }
542  {
543  --it_;
544  return *this;
545  }
547  {
548  return IteratorWrapper{it_--};
549  }
551  {
552  return IteratorWrapper{wrap.owner_, wrap.it_ + n};
553  }
555  {
556  return IteratorWrapper{wrap.owner_, wrap.it_ - n};
557  }
559  {
560  return it_ - other.it_;
561  }
562  auto operator*()
563  {
564  if constexpr (std::is_same_v<WrappedIterator, typename ContainerT::reverse_iterator>)
566  owner_,
567  owner_->contained_.size() - static_cast<std::size_t>(1) -
568  static_cast<std::size_t>(it_ - owner_->contained_.rbegin()),
569  *it_};
570  else
572  owner_, static_cast<std::size_t>(it_ - owner_->contained_.begin()), *it_};
573  }
574  auto operator*() const
575  {
576  return *it_;
577  }
578  auto operator->()
579  {
580  if constexpr (std::is_same_v<WrappedIterator, typename ContainerT::reverse_iterator>)
582  owner_,
583  owner_->contained_.size() - static_cast<std::size_t>(1) -
584  static_cast<std::size_t>(it_ - owner_->contained_.rbegin()),
585  &*it_};
586  else
588  owner_, static_cast<std::size_t>(it_ - owner_->contained_.begin()), &*it_};
589  }
590  auto operator->() const
591  {
592  return &*it_;
593  }
594  IteratorWrapper operator[](std::size_t offset) const
595  {
596  return IteratorWrapper{owner_, it_[offset]};
597  }
598  bool operator<(IteratorWrapper const& other) const
599  {
600  return it_ < other.it_;
601  }
602  bool operator>(IteratorWrapper const& other) const
603  {
604  return it_ > other.it_;
605  }
606  bool operator<=(IteratorWrapper const& other) const
607  {
608  return it_ <= other.it_;
609  }
610  bool operator>=(IteratorWrapper const& other) const
611  {
612  return it_ >= other.it_;
613  }
614  bool operator==(IteratorWrapper const& other) const
615  {
616  return it_ == other.it_;
617  }
618  WrappedIterator getWrapped() const
619  {
620  return it_;
621  }
622 
623  private:
625  WrappedIterator it_;
626  };
627  };
628 
629  template <typename ContainerT>
630  class ObservedContainer : public ModifiableObserved<ContainerT>
631  {
632  public:
633  friend class ContainerWrapUtility::ReferenceWrapper<typename ContainerT::value_type, ContainerT>;
634  friend class ContainerWrapUtility::PointerWrapper<typename ContainerT::value_type, ContainerT>;
635 
636  using value_type = typename ContainerT::value_type;
637  using allocator_type = typename ContainerT::allocator_type;
638  using size_type = typename ContainerT::size_type;
639  using difference_type = typename ContainerT::difference_type;
640  using reference = ContainerWrapUtility::ReferenceWrapper<typename ContainerT::value_type, ContainerT>;
641  using const_reference = typename ContainerT::const_reference;
642  using pointer = ContainerWrapUtility::PointerWrapper<typename ContainerT::value_type, ContainerT>;
643  using const_pointer = typename ContainerT::const_pointer;
644 
645  using iterator = ContainerWrapUtility::IteratorWrapper<typename ContainerT::iterator, ContainerT>;
646  using const_iterator = typename ContainerT::const_iterator;
648  ContainerWrapUtility::IteratorWrapper<typename ContainerT::reverse_iterator, ContainerT>;
649  using const_reverse_iterator = typename ContainerT::const_reverse_iterator;
650 
651  using ModifiableObserved<ContainerT>::contained_;
652 
653  public:
654  explicit ObservedContainer(CustomEventContextFlag_t, EventContext* ctx)
655  : ModifiableObserved<ContainerT>{CustomEventContextFlag, ctx}
656  , rangeContext_{std::make_shared<RangeEventContext>()}
658  {}
659  explicit ObservedContainer()
660  : ModifiableObserved<ContainerT>{}
661  , rangeContext_{std::make_shared<RangeEventContext>()}
663  {}
664  template <typename T = ContainerT>
666  : ModifiableObserved<ContainerT>{CustomEventContextFlag, ctx, std::forward<T>(t)}
667  , rangeContext_{std::make_shared<RangeEventContext>()}
669  {}
670  template <typename T = ContainerT>
671  explicit ObservedContainer(T&& t)
672  : ModifiableObserved<ContainerT>{std::forward<T>(t)}
673  , rangeContext_{std::make_shared<RangeEventContext>()}
675  {}
677  : ModifiableObserved<ContainerT>{}
678  , rangeContext_{std::make_shared<RangeEventContext>(std::move(rangeContext))}
680  {}
682  : ModifiableObserved<ContainerT>{CustomEventContextFlag, ctx}
683  , rangeContext_{std::make_shared<RangeEventContext>(std::move(rangeContext))}
685  {}
686  template <typename T = ContainerT>
688  : ModifiableObserved<ContainerT>{std::forward<T>(t)}
689  , rangeContext_{std::make_shared<RangeEventContext>(std::move(rangeContext))}
691  {}
692  template <typename T = ContainerT>
694  : ModifiableObserved<ContainerT>{CustomEventContextFlag, ctx, std::forward<T>(t)}
695  , rangeContext_{std::make_shared<RangeEventContext>(std::move(rangeContext))}
697  {}
698 
704  {
705  if (!moveDetector_.wasMoved())
707  }
708 
709  constexpr auto map(auto&& function) const;
710  constexpr auto map(auto&& function);
711 
712  template <typename T = ContainerT>
714  {
715  contained_ = std::forward<T>(t);
716  rangeContext_->reset(true);
717  update();
718  return *this;
719  }
720  void assign(size_type count, const value_type& value)
721  {
722  contained_.assign(count, value);
723  rangeContext_->reset(true);
724  update();
725  }
726  template <typename Iterator>
727  void assign(Iterator first, Iterator last)
728  {
729  contained_.assign(first, last);
730  rangeContext_->reset(true);
731  update();
732  }
733  void assign(std::initializer_list<value_type> ilist)
734  {
735  contained_.assign(ilist);
736  rangeContext_->reset(true);
737  update();
738  }
739 
740  // Element access
742  {
743  return reference{this, 0, contained_.front()};
744  }
746  {
747  return contained_.front();
748  }
750  {
751  return reference{this, contained_.size() - 1, contained_.back()};
752  }
754  {
755  return contained_.back();
756  }
757  pointer data() noexcept
758  {
759  return pointer{this, 0, contained_.data()};
760  }
761  const_pointer data() const noexcept
762  {
763  return contained_.data();
764  }
766  {
767  return reference{this, pos, contained_.at(pos)};
768  }
770  {
771  return contained_.at(pos);
772  }
774  {
775  return reference{this, pos, contained_[pos]};
776  }
778  {
779  return contained_[pos];
780  }
781 
782  // Iterators
783  iterator begin() noexcept
784  {
785  return iterator{this, contained_.begin()};
786  }
787  const_iterator begin() const noexcept
788  {
789  return contained_.begin();
790  }
791  iterator end() noexcept
792  {
793  return iterator{this, contained_.end()};
794  }
795  const_iterator end() const noexcept
796  {
797  return contained_.end();
798  }
799  const_iterator cbegin() const noexcept
800  {
801  return contained_.cbegin();
802  }
803  const_iterator cend() const noexcept
804  {
805  return contained_.cend();
806  }
808  {
809  return reverse_iterator{this, contained_.rbegin()};
810  }
812  {
813  return contained_.rbegin();
814  }
816  {
817  return reverse_iterator{this, contained_.rend()};
818  }
819  const_reverse_iterator rend() const noexcept
820  {
821  return contained_.rend();
822  }
824  {
825  return contained_.crbegin();
826  }
827  const_reverse_iterator crend() const noexcept
828  {
829  return contained_.crend();
830  }
831 
832  // Capacity
833  bool empty() const noexcept
834  {
835  return contained_.empty();
836  }
837  std::size_t size() const noexcept
838  {
839  return contained_.size();
840  }
841  template <typename U = ContainerT>
843  {
844  return contained_.max_size();
845  }
846  template <typename U = ContainerT>
847  Detail::PickFirst_t<void, decltype(std::declval<U>().reserve(std::declval<std::size_t>()))>
849  {
850  return contained_.reserve(capacity);
851  }
852  template <typename U = ContainerT>
854  {
855  return contained_.capacity();
856  }
857  template <typename U = ContainerT>
859  {
860  return contained_.shrink_to_fit();
861  }
862 
863  // Modifiers
864  void clear()
865  {
866  contained_.clear();
867  rangeContext_->reset(true);
868  update();
869  }
870  template <typename U = ContainerT>
872  std::pair<typename ContainerT::iterator, bool>,
873  decltype(std::declval<U>().insert(std::declval<const value_type&>()))>
875  {
876  NUI_ASSERT(ObservedBase::eventContext_ != nullptr, "Event context must never be null.");
877 
878  const auto result = contained_.insert(value);
879  rangeContext_->performFullRangeUpdate();
880  update();
882  return result;
883  }
884  template <typename U = ContainerT>
886  std::pair<typename ContainerT::iterator, bool>,
887  decltype(std::declval<U>().insert(std::declval<value_type&&>()))>
889  {
890  NUI_ASSERT(ObservedBase::eventContext_ != nullptr, "Event context must never be null.");
891 
892  const auto result = contained_.insert(std::move(value));
893  rangeContext_->performFullRangeUpdate();
894  update();
896  return result;
897  }
899  {
900  return insert(pos.getWrapped(), value);
901  }
903  {
904  const auto distance = pos - cbegin();
905  auto it = contained_.insert(pos, value);
906  insertRangeChecked(distance, distance, RangeOperationType::Insert);
907  return iterator{this, it};
908  }
910  {
911  return insert(pos.getWrapped(), std::move(value));
912  }
914  {
915  const auto distance = pos - cbegin();
916  auto it = contained_.insert(pos, std::move(value));
917  insertRangeChecked(distance, distance, RangeOperationType::Insert);
918  return iterator{this, it};
919  }
921  {
922  return insert(pos.getWrapped(), count, value);
923  }
925  {
926  const auto distance = pos - cbegin();
927  auto it = contained_.insert(pos, count, value);
928  insertRangeChecked(distance, distance + count - 1, RangeOperationType::Insert);
929  return iterator{this, it};
930  }
931  template <typename Iterator>
932  iterator insert(iterator pos, Iterator first, Iterator last)
933  {
934  return insert(pos.getWrapped(), first, last);
935  }
936  template <typename Iterator>
937  iterator insert(const_iterator pos, Iterator first, Iterator last)
938  {
939  const auto distance = pos - cbegin();
940  auto it = contained_.insert(pos, first, last);
941  insertRangeChecked(distance, distance + std::distance(first, last) - 1, RangeOperationType::Insert);
942  return iterator{this, it};
943  }
944  iterator insert(iterator pos, std::initializer_list<value_type> ilist)
945  {
946  return insert(pos.getWrapped(), ilist);
947  }
948  iterator insert(const_iterator pos, std::initializer_list<value_type> ilist)
949  {
950  const auto distance = pos - cbegin();
951  auto it = contained_.insert(pos, ilist);
952  insertRangeChecked(distance, distance + ilist.size() - 1, RangeOperationType::Insert);
953  return iterator{this, it};
954  }
955  template <typename... Args>
956  iterator emplace(const_iterator pos, Args&&... args)
957  {
958  const auto distance = pos - cbegin();
959  auto it = contained_.emplace(pos, std::forward<Args>(args)...);
960  insertRangeChecked(distance, distance, RangeOperationType::Insert);
961  return iterator{this, it};
962  }
964  {
965  const auto distance = pos - begin();
966  eraseNotify(distance, distance);
967  auto it = contained_.erase(pos.getWrapped());
968  insertRangeChecked(distance, distance, RangeOperationType::Erase);
969  return iterator{this, it};
970  }
972  {
973  const auto distance = pos - cbegin();
974  eraseNotify(distance, distance);
975  auto it = contained_.erase(pos);
976  insertRangeChecked(distance, distance, RangeOperationType::Erase);
977  return iterator{this, it};
978  }
980  {
981  const auto distance = first - begin();
982  const auto distance2 = std::distance(first, last);
983  eraseNotify(distance, distance + distance2 - 1);
984  auto it = contained_.erase(first.getWrapped(), last.getWrapped());
985  insertRangeChecked(distance, distance + distance2 - 1, RangeOperationType::Erase);
986  return iterator{this, it};
987  }
989  {
990  const auto distance = first - cbegin();
991  const auto distance2 = std::distance(first, last);
992  eraseNotify(distance, distance + distance2 - 1);
993  auto it = contained_.erase(first, last);
994  insertRangeChecked(distance, distance + distance2 - 1, RangeOperationType::Erase);
995  return iterator{this, it};
996  }
997  template <typename U = ContainerT>
998  Detail::PickFirst_t<void, decltype(std::declval<U>().push_back(std::declval<const value_type&>()))>
1000  {
1001  contained_.push_back(value);
1003  }
1004  template <typename U = ContainerT>
1005  Detail::PickFirst_t<void, decltype(std::declval<U>().push_back(std::declval<value_type>()))>
1007  {
1008  contained_.push_back(std::move(value));
1010  }
1011  template <typename U = ContainerT>
1012  Detail::PickFirst_t<void, decltype(std::declval<U>().push_front(std::declval<const value_type&>()))>
1014  {
1015  contained_.push_front(value);
1017  }
1018  template <typename U = ContainerT>
1019  Detail::PickFirst_t<void, decltype(std::declval<U>().push_front(std::declval<value_type>()))>
1021  {
1022  contained_.push_front(std::move(value));
1024  }
1025  template <typename... Args>
1026  void emplace_back(Args&&... args)
1027  {
1028  contained_.emplace_back(std::forward<Args>(args)...);
1030  }
1031  template <typename U = ContainerT, typename... Args>
1033  {
1034  contained_.emplace_front(std::forward<Args>(args)...);
1036  }
1037  void pop_back()
1038  {
1039  if (contained_.empty())
1040  return;
1041  eraseNotify(size() - 1, size() - 1);
1042  contained_.pop_back();
1044  }
1045  template <typename U = ContainerT>
1047  {
1048  if (contained_.empty())
1049  return;
1050  eraseNotify(0, 0);
1051  contained_.pop_front();
1053  }
1054  template <typename U = ContainerT>
1055  Detail::PickFirst_t<void, decltype(std::declval<U>().resize(std::declval<std::size_t>()))>
1057  {
1058  const auto sizeBefore = contained_.size();
1059  if (sizeBefore < count && sizeBefore != 0)
1060  {
1061  eraseNotify(sizeBefore, count - 1);
1062  }
1063  contained_.resize(count);
1064  if (sizeBefore < count)
1065  {
1066  insertRangeChecked(sizeBefore, count - 1, RangeOperationType::Insert);
1067  }
1068  else if (sizeBefore != 0)
1069  {
1070  insertRangeChecked(count, sizeBefore - 1, RangeOperationType::Erase);
1071  }
1072  }
1073  template <typename U = ContainerT>
1075  void,
1076  decltype(std::declval<U>().resize(std::declval<std::size_t>(), std::declval<value_type const&>()))>
1077  resize(size_type count, value_type const& fillValue)
1078  {
1079  const auto sizeBefore = contained_.size();
1080  eraseNotify(sizeBefore, count - 1);
1081  contained_.resize(count, fillValue);
1082  if (sizeBefore < count)
1083  {
1084  insertRangeChecked(sizeBefore, count - 1, RangeOperationType::Insert);
1085  }
1086  else if (sizeBefore != 0)
1087  {
1088  insertRangeChecked(count, sizeBefore - 1, RangeOperationType::Erase);
1089  }
1090  }
1091  void swap(ContainerT& other)
1092  {
1093  contained_.swap(other);
1094  rangeContext_->reset(true);
1095  update();
1096  }
1097 
1098  // Other
1099  ContainerT& value()
1100  {
1101  return contained_;
1102  }
1103  ContainerT const& value() const
1104  {
1105  return contained_;
1106  }
1108  {
1109  return *rangeContext_;
1110  }
1112  {
1113  return *rangeContext_;
1114  }
1115 
1116  protected:
1117  void update(bool force = false) const override
1118  {
1119  if (force)
1120  rangeContext_->reset(true);
1122  ObservedBase::update(force);
1123  }
1124 
1125  protected:
1126  void insertRangeChecked(std::size_t low, std::size_t high, RangeOperationType type)
1127  {
1128  std::function<void(int)> doInsert;
1129  doInsert = [&](int retries) {
1130  NUI_ASSERT(ObservedBase::eventContext_ != nullptr, "Event context must never be null.");
1131 
1132  const auto result = rangeContext_->insertModificationRange(low, high, type);
1134  {
1135  update();
1137  }
1139  {
1140  update();
1142 
1143  if (retries < 3)
1144  doInsert(retries + 1);
1145  else
1146  {
1147  rangeContext_->reset(true);
1148  update();
1150  return;
1151  }
1152  }
1153  else if (result == RangeEventContext::InsertResult::Accepted)
1154  {
1155  update();
1156  }
1157  else
1158  {
1159  // Rejected! (why?)
1160  rangeContext_->reset(true);
1161  update();
1163  return;
1164  }
1165  };
1166 
1167  doInsert(0);
1168  }
1169 
1171  {
1172  NUI_ASSERT(ObservedBase::eventContext_ != nullptr, "Event context must never be null.");
1174  Event{[weak = std::weak_ptr<RangeEventContext>{rangeContext_}](EventContext::EventIdType) {
1175  if (auto shared = weak.lock(); shared)
1176  {
1177  shared->reset();
1178  return true;
1179  }
1180  return false;
1181  }});
1182  }
1183 
1184  void eraseNotify(std::size_t index, std::size_t high)
1185  {
1186  const bool fixupPerformed = rangeContext_->eraseNotify(index, high);
1187  if (fixupPerformed) // FORCE update:
1188  {
1189  update();
1191  }
1192  }
1193 
1194  protected:
1196  mutable std::shared_ptr<RangeEventContext> rangeContext_;
1198  };
1199 
1200  template <typename T>
1201  class Observed : public ModifiableObserved<T>
1202  {
1203  public:
1207 
1208  Observed& operator=(T const& contained)
1209  {
1211  return *this;
1212  }
1213  Observed& operator=(T&& contained)
1214  {
1215  ModifiableObserved<T>::operator=(std::move(contained));
1216  return *this;
1217  }
1218  };
1219  template <typename... Parameters>
1220  class Observed<std::vector<Parameters...>> : public ObservedContainer<std::vector<Parameters...>>
1221  {
1222  public:
1223  using ObservedContainer<std::vector<Parameters...>>::ObservedContainer;
1224  using ObservedContainer<std::vector<Parameters...>>::operator=;
1225  using ObservedContainer<std::vector<Parameters...>>::operator->;
1226  static constexpr auto isRandomAccess = true;
1227 
1228  Observed<std::vector<Parameters...>>& operator=(std::vector<Parameters...> const& contained)
1229  {
1230  ObservedContainer<std::vector<Parameters...>>::operator=(contained);
1231  return *this;
1232  }
1233  Observed<std::vector<Parameters...>>& operator=(std::vector<Parameters...>&& contained)
1234  {
1235  ObservedContainer<std::vector<Parameters...>>::operator=(std::move(contained));
1236  return *this;
1237  }
1238  };
1239  template <typename... Parameters>
1240  class Observed<std::deque<Parameters...>> : public ObservedContainer<std::deque<Parameters...>>
1241  {
1242  public:
1243  using ObservedContainer<std::deque<Parameters...>>::ObservedContainer;
1244  using ObservedContainer<std::deque<Parameters...>>::operator=;
1245  using ObservedContainer<std::deque<Parameters...>>::operator->;
1246  static constexpr auto isRandomAccess = true;
1247 
1248  Observed<std::deque<Parameters...>>& operator=(std::deque<Parameters...> const& contained)
1249  {
1250  ObservedContainer<std::deque<Parameters...>>::operator=(contained);
1251  return *this;
1252  }
1253  Observed<std::deque<Parameters...>>& operator=(std::deque<Parameters...>&& contained)
1254  {
1255  ObservedContainer<std::deque<Parameters...>>::operator=(std::move(contained));
1256  return *this;
1257  }
1258  };
1259  template <typename... Parameters>
1260  class Observed<std::basic_string<Parameters...>> : public ObservedContainer<std::basic_string<Parameters...>>
1261  {
1262  public:
1263  using ObservedContainer<std::basic_string<Parameters...>>::ObservedContainer;
1264  using ObservedContainer<std::basic_string<Parameters...>>::operator=;
1265  using ObservedContainer<std::basic_string<Parameters...>>::operator->;
1266  static constexpr auto isRandomAccess = true;
1267 
1268  Observed<std::basic_string<Parameters...>>& operator=(std::basic_string<Parameters...> const& contained)
1269  {
1270  ObservedContainer<std::basic_string<Parameters...>>::operator=(contained);
1271  return *this;
1272  }
1273  Observed<std::basic_string<Parameters...>>& operator=(std::basic_string<Parameters...>&& contained)
1274  {
1275  ObservedContainer<std::basic_string<Parameters...>>::operator=(std::move(contained));
1276  return *this;
1277  }
1278 
1279  Observed<std::basic_string<Parameters...>>& erase(std::size_t index = 0, std::size_t count = std::string::npos)
1280  {
1281  if (count == std::size_t{0})
1282  return *this;
1283  const auto sizeBefore = this->contained_.size();
1284  const auto high = count == std::string::npos ? sizeBefore - 1 : count - 1;
1285  this->eraseNotify(index, high);
1286  this->contained_.erase(index, count);
1287  this->insertRangeChecked(index, high, RangeOperationType::Erase);
1288  return *this;
1289  }
1290  };
1291  template <typename... Parameters>
1292  class Observed<std::set<Parameters...>> : public ObservedContainer<std::set<Parameters...>>
1293  {
1294  public:
1295  using ObservedContainer<std::set<Parameters...>>::ObservedContainer;
1296  using ObservedContainer<std::set<Parameters...>>::operator=;
1297  using ObservedContainer<std::set<Parameters...>>::operator->;
1298  static constexpr auto isRandomAccess = false;
1299 
1300  public:
1302  : ObservedContainer<std::set<Parameters...>>{RangeEventContext{true}}
1303  {}
1304  template <typename T = std::set<Parameters...>>
1305  explicit Observed(T&& t)
1306  : ObservedContainer<std::set<Parameters...>>{std::forward<T>(t), RangeEventContext{true}}
1307  {}
1308 
1309  Observed<std::set<Parameters...>>& operator=(std::set<Parameters...> const& contained)
1310  {
1311  ObservedContainer<std::set<Parameters...>>::operator=(contained);
1312  return *this;
1313  }
1314  Observed<std::set<Parameters...>>& operator=(std::set<Parameters...>&& contained)
1315  {
1316  ObservedContainer<std::set<Parameters...>>::operator=(std::move(contained));
1317  return *this;
1318  }
1319  };
1320  template <typename... Parameters>
1321  class Observed<std::list<Parameters...>> : public ObservedContainer<std::list<Parameters...>>
1322  {
1323  public:
1324  using ObservedContainer<std::list<Parameters...>>::ObservedContainer;
1325  using ObservedContainer<std::list<Parameters...>>::operator=;
1326  using ObservedContainer<std::list<Parameters...>>::operator->;
1327  static constexpr auto isRandomAccess = false;
1328 
1329  public:
1331  : ObservedContainer<std::list<Parameters...>>{RangeEventContext{true}}
1332  {}
1333  template <typename T = std::list<Parameters...>>
1334  explicit Observed(T&& t)
1335  : ObservedContainer<std::list<Parameters...>>{std::forward<T>(t), RangeEventContext{true}}
1336  {}
1337 
1338  Observed<std::list<Parameters...>>& operator=(std::list<Parameters...> const& contained)
1339  {
1340  ObservedContainer<std::list<Parameters...>>::operator=(contained);
1341  return *this;
1342  }
1343  Observed<std::list<Parameters...>>& operator=(std::list<Parameters...>&& contained)
1344  {
1345  ObservedContainer<std::list<Parameters...>>::operator=(std::move(contained));
1346  return *this;
1347  }
1348  };
1349 
1350  template <>
1352  {
1353  public:
1355  using ObservedBase::operator=;
1356 
1357  void modify() const
1358  {
1359  update();
1360  };
1361 
1362  void modifyNow() const
1363  {
1364  updateNow();
1365  };
1366  };
1367 
1368  namespace Detail
1369  {
1370  template <typename T>
1371  struct IsObserved
1372  {
1373  static constexpr bool value = false;
1374  };
1375 
1376  template <typename T>
1378  {
1379  static constexpr bool value = true;
1380  };
1381 
1382  template <typename T>
1384  {
1385  static constexpr bool value = false;
1386  };
1387 
1388  template <typename T>
1389  struct IsWeakObserved<std::weak_ptr<Observed<T>>>
1390  {
1391  static constexpr bool value = true;
1392  };
1393 
1394  template <typename T>
1396  {
1397  static constexpr bool value = false;
1398  };
1399 
1400  template <typename T>
1401  struct IsSharedObserved<std::shared_ptr<Observed<T>>>
1402  {
1403  static constexpr bool value = true;
1404  };
1405 
1406  template <typename T>
1408  {
1409  static constexpr bool value =
1411  };
1412  }
1413 
1414  template <typename T>
1415  requires Incrementable<T>
1417  {
1418  ++observedValue.value();
1419  observedValue.update();
1420  return observedValue;
1421  }
1422  template <typename T>
1423  requires Incrementable<T>
1424  inline T operator++(ModifiableObserved<T>& observedValue, int)
1425  {
1426  auto tmp = observedValue.value();
1427  ++observedValue.value();
1428  observedValue.update();
1429  return tmp;
1430  }
1431 
1432  template <typename T>
1433  inline auto operator--(ModifiableObserved<T>& observedValue)
1434  -> ModifiableObserved<Detail::PickFirst_t<T, decltype(--std::declval<T>())>>&
1435  {
1436  --observedValue.value();
1437  observedValue.update();
1438  return observedValue;
1439  }
1440  template <typename T>
1441  inline auto
1443  {
1444  auto tmp = observedValue.value();
1445  --observedValue.value();
1446  observedValue.update();
1447  return tmp;
1448  }
1449 
1450  template <typename T>
1452  template <typename T>
1454  template <typename T>
1456  template <typename T>
1458 
1459  namespace Detail
1460  {
1461  template <typename T>
1462  struct CopyableObservedWrap // minimal wrapper to make Observed<T> copiable
1463  {
1464  public:
1465  explicit constexpr CopyableObservedWrap(Observed<T> const& observed)
1466  : observed_{&observed}
1467  {}
1468 
1469  inline T const& value() const
1470  {
1471  return observed_->value();
1472  }
1473 
1474  inline void attachEvent(auto eventId) const
1475  {
1476  observed_->attachEvent(eventId);
1477  }
1478 
1479  inline void detachEvent(auto eventId) const
1480  {
1481  observed_->detachEvent(eventId);
1482  }
1483 
1484  private:
1485  Observed<T> const* observed_;
1486  };
1487 
1488  template <typename T>
1490  {
1491  using type = T const&;
1492  };
1493  template <>
1495  {
1496  using type = void;
1497  };
1498  template <typename T>
1499  struct ObservedAddReference<std::weak_ptr<Observed<T>>>
1500  {
1501  using type = std::weak_ptr<Observed<T>>;
1502  };
1503  template <typename T>
1504  struct ObservedAddReference<std::shared_ptr<Observed<T>>>
1505  {
1506  using type = std::weak_ptr<Observed<T>>;
1507  };
1508  template <typename T>
1509  struct ObservedAddReference<std::weak_ptr<const Observed<T>>>
1510  {
1511  using type = std::weak_ptr<const Observed<T>>;
1512  };
1513  template <typename T>
1514  struct ObservedAddReference<std::shared_ptr<const Observed<T>>>
1515  {
1516  using type = std::weak_ptr<const Observed<T>>;
1517  };
1518 
1519  template <typename T>
1521  {
1522  using type = T&;
1523  using raw = T;
1524  };
1525  template <>
1527  {
1528  using type = void;
1529  using raw = void;
1530  };
1531  template <typename T>
1532  struct ObservedAddMutableReference<std::weak_ptr<Observed<T>>>
1533  {
1534  using type = std::weak_ptr<Observed<T>>;
1535  using raw = Observed<T>;
1536  };
1537  template <typename T>
1538  struct ObservedAddMutableReference<std::shared_ptr<Observed<T>>>
1539  {
1540  using type = std::weak_ptr<Observed<T>>;
1541  using raw = Observed<T>;
1542  };
1543 
1544  template <typename T>
1546  template <typename T>
1548  template <typename T>
1550  }
1551 
1552  template <typename T>
1554  {
1555  using type = T;
1556  };
1557  template <typename T>
1559  {
1560  using type = T;
1561  };
1562  template <typename T>
1563  struct UnpackObserved<std::weak_ptr<Observed<T>>>
1564  {
1565  using type = T;
1566  };
1567  template <typename T>
1568  struct UnpackObserved<std::shared_ptr<Observed<T>>>
1569  {
1570  using type = T;
1571  };
1572  template <typename T>
1573  struct UnpackObserved<std::weak_ptr<const Observed<T>>>
1574  {
1575  using type = T;
1576  };
1577  template <typename T>
1578  struct UnpackObserved<std::shared_ptr<const Observed<T>>>
1579  {
1580  using type = T;
1581  };
1582  template <typename T>
1584 }
#define NUI_ASSERT(condition, message)
Definition: assert.hpp:31
Definition: observed_value.hpp:505
auto operator->() const
Definition: observed_value.hpp:590
IteratorWrapper operator++(int)
Definition: observed_value.hpp:537
std::random_access_iterator_tag iterator_category
Definition: observed_value.hpp:507
auto operator*()
Definition: observed_value.hpp:562
IteratorWrapper(ObservedContainer< ContainerT > *owner, WrappedIterator it)
Definition: observed_value.hpp:514
friend IteratorWrapper operator-(IteratorWrapper const &wrap, difference_type n)
Definition: observed_value.hpp:554
IteratorWrapper operator[](std::size_t offset) const
Definition: observed_value.hpp:594
IteratorWrapper & operator-=(difference_type n)
Definition: observed_value.hpp:527
auto operator->()
Definition: observed_value.hpp:578
typename WrappedIterator::value_type value_type
Definition: observed_value.hpp:508
WrappedIterator getWrapped() const
Definition: observed_value.hpp:618
bool operator<(IteratorWrapper const &other) const
Definition: observed_value.hpp:598
IteratorWrapper(IteratorWrapper const &)=default
IteratorWrapper & operator+=(difference_type n)
Definition: observed_value.hpp:522
bool operator>=(IteratorWrapper const &other) const
Definition: observed_value.hpp:610
IteratorWrapper & operator=(IteratorWrapper const &)=default
difference_type operator-(IteratorWrapper const &other) const
Definition: observed_value.hpp:558
IteratorWrapper operator--(int)
Definition: observed_value.hpp:546
friend IteratorWrapper operator+(IteratorWrapper const &wrap, difference_type n)
Definition: observed_value.hpp:550
IteratorWrapper & operator++()
Definition: observed_value.hpp:532
IteratorWrapper(IteratorWrapper &&)=default
bool operator==(IteratorWrapper const &other) const
Definition: observed_value.hpp:614
bool operator>(IteratorWrapper const &other) const
Definition: observed_value.hpp:602
auto operator*() const
Definition: observed_value.hpp:574
bool operator<=(IteratorWrapper const &other) const
Definition: observed_value.hpp:606
typename WrappedIterator::difference_type difference_type
Definition: observed_value.hpp:509
IteratorWrapper & operator--()
Definition: observed_value.hpp:541
IteratorWrapper & operator=(IteratorWrapper &&)=default
Definition: observed_value.hpp:453
T & operator*()
Definition: observed_value.hpp:464
void operator=(T *ptr)
Definition: observed_value.hpp:491
T const & operator*() const
Definition: observed_value.hpp:469
ObservedContainer< ContainerT > * owner_
Definition: observed_value.hpp:498
T * operator->()
Definition: observed_value.hpp:473
std::size_t pos_
Definition: observed_value.hpp:499
T * ptr_
Definition: observed_value.hpp:500
T const & getReadonly()
Definition: observed_value.hpp:487
T const * operator->() const
Definition: observed_value.hpp:478
T & get()
Definition: observed_value.hpp:482
PointerWrapper(ObservedContainer< ContainerT > *owner, std::size_t pos, T *ptr) noexcept
Definition: observed_value.hpp:455
Definition: observed_value.hpp:353
T const & operator*() const
Definition: observed_value.hpp:393
T const & getReadonly()
Definition: observed_value.hpp:411
T * ref_
Definition: observed_value.hpp:429
std::size_t pos_
Definition: observed_value.hpp:428
T & get()
Definition: observed_value.hpp:406
void operator=(T const &val)
Definition: observed_value.hpp:420
ReferenceWrapper(ReferenceWrapper &&other) noexcept
Definition: observed_value.hpp:361
T * operator->()
Definition: observed_value.hpp:397
ReferenceWrapper(ReferenceWrapper const &)=default
T const * operator->() const
Definition: observed_value.hpp:402
ReferenceWrapper & operator=(ReferenceWrapper const &)=default
T & operator*()
Definition: observed_value.hpp:388
void operator=(T &&val)
Definition: observed_value.hpp:415
ObservedContainer< ContainerT > * owner_
Definition: observed_value.hpp:427
ReferenceWrapper(ObservedContainer< ContainerT > *owner, std::size_t pos, T &ref)
Definition: observed_value.hpp:355
ReferenceWrapper & operator=(ReferenceWrapper &&other) noexcept
Definition: observed_value.hpp:371
This object can be copied with low cost.
Definition: event_context.hpp:38
void removeAfterEffect(EventIdType id)
Definition: event_context.hpp:80
EventIdType registerAfterEffect(Event event)
Definition: event_context.hpp:72
auto activateEvent(EventIdType id)
Definition: event_context.hpp:56
auto activateAfterEffect(EventIdType id)
Definition: event_context.hpp:60
EventRegistry::EventIdType EventIdType
Definition: event_context.hpp:40
void executeActiveEventsImmediately()
Definition: event_context.hpp:64
constexpr static EventIdType invalidEventId
Definition: event_registry.hpp:18
Definition: event.hpp:40
Definition: observed_value.hpp:139
auto & operator*()
Definition: observed_value.hpp:171
auto * operator->()
Definition: observed_value.hpp:167
ModificationProxy(ModifiableObserved &observed)
Definition: observed_value.hpp:141
ModificationProxy(ModifiableObserved &observed, bool now)
Definition: observed_value.hpp:145
~ModificationProxy()
Definition: observed_value.hpp:149
auto & value()
Definition: observed_value.hpp:163
Definition: observed_value.hpp:133
ModifiableObserved(T &&t)
Definition: observed_value.hpp:223
void assignWithoutUpdate(ContainedT &&t)
Sets the value without making an update.
Definition: observed_value.hpp:337
ModificationProxy modify()
Can be used to make mutations to the underlying class that get commited when the returned proxy is de...
Definition: observed_value.hpp:293
requires std::equality_comparable_with< ContainedT, T > &&Fundamental< T > &&Fundamental< ContainedT > ModifiableObserved & operator=(T &&t)
Definition: observed_value.hpp:270
ModifiableObserved(CustomEventContextFlag_t, EventContext *ctx)
Definition: observed_value.hpp:228
requires PlusAssignable< T, U > ModifiableObserved< T > & operator+=(U const &rhs)
Definition: observed_value.hpp:255
ContainedT const * operator->() const
Definition: observed_value.hpp:329
ContainedT & operator*()
Definition: observed_value.hpp:317
ModifiableObserved(ModifiableObserved &&other)
Definition: observed_value.hpp:191
requires MinusAssignable< T, U > ModifiableObserved< T > & operator-=(U const &rhs)
Definition: observed_value.hpp:262
ModifiableObserved()
Definition: observed_value.hpp:186
ModificationProxy modifyNow()
Definition: observed_value.hpp:298
ModifiableObserved & operator=(ModifiableObserved &&other)
Definition: observed_value.hpp:198
ContainedT value_type
Definition: observed_value.hpp:135
ModifiableObserved & operator=(ContainedT const &contained)
Definition: observed_value.hpp:208
requires std::equality_comparable_with< ContainedT, T > ModifiableObserved & assignChecked(T &&other)
Definition: observed_value.hpp:277
ModifiableObserved(const ModifiableObserved &)=delete
ContainedT const & value() const
Definition: observed_value.hpp:313
ContainedT contained_
Definition: observed_value.hpp:343
ModifiableObserved & operator=(ContainedT &&contained)
Definition: observed_value.hpp:214
ModifiableObserved & operator=(T &&t)
Assign a completely new value.
Definition: observed_value.hpp:246
ModifiableObserved(CustomEventContextFlag_t, EventContext *ctx, T &&t)
Definition: observed_value.hpp:234
ModifiableObserved & operator=(const ModifiableObserved &)=delete
ContainedT * operator->()
Definition: observed_value.hpp:325
ContainedT const & operator*() const
Definition: observed_value.hpp:321
Utility class to detect if an object was moved.
Definition: move_detector.hpp:9
bool wasMoved() const noexcept
Definition: move_detector.hpp:24
Definition: observed_value.hpp:30
std::size_t totalAttachedEventCount() const
Definition: observed_value.hpp:85
void attachOneshotEvent(EventContext::EventIdType eventId) const
Definition: observed_value.hpp:66
std::size_t attachedOneshotEventCount() const
Definition: observed_value.hpp:81
void detachAllEvents()
You should never need to do this.
Definition: observed_value.hpp:93
virtual void update(bool=false) const
Definition: observed_value.hpp:99
ObservedBase & operator=(ObservedBase const &)=delete
ObservedBase(CustomEventContextFlag_t, EventContext *ctx)
Definition: observed_value.hpp:32
std::size_t attachedEventCount() const
Definition: observed_value.hpp:77
ObservedBase(ObservedBase const &)=delete
void attachEvent(EventContext::EventIdType eventId) const
Definition: observed_value.hpp:62
ObservedBase & operator=(ObservedBase &&other)
Definition: observed_value.hpp:52
void detachEvent(EventContext::EventIdType eventId) const
Definition: observed_value.hpp:70
ObservedBase(ObservedBase &&other)
Definition: observed_value.hpp:39
void updateNow(bool force=false) const
Definition: observed_value.hpp:117
virtual ~ObservedBase()=default
EventContext * eventContext_
Definition: observed_value.hpp:126
std::vector< EventContext::EventIdType > attachedEvents_
Definition: observed_value.hpp:127
std::vector< EventContext::EventIdType > attachedOneshotEvents_
Definition: observed_value.hpp:128
Definition: observed_value.hpp:631
ObservedContainer(CustomEventContextFlag_t, EventContext *ctx, RangeEventContext &&rangeContext)
Definition: observed_value.hpp:681
ObservedContainer()
Definition: observed_value.hpp:659
iterator erase(const_iterator first, const_iterator last)
Definition: observed_value.hpp:988
iterator insert(iterator pos, std::initializer_list< value_type > ilist)
Definition: observed_value.hpp:944
~ObservedContainer()
Definition: observed_value.hpp:703
void swap(ContainerT &other)
Definition: observed_value.hpp:1091
const_reference front() const
Definition: observed_value.hpp:745
std::shared_ptr< RangeEventContext > rangeContext_
Definition: observed_value.hpp:1196
const_reference at(size_type pos) const
Definition: observed_value.hpp:769
Detail::PickFirst_t< std::pair< typename ContainerT::iterator, bool >, decltype(std::declval< U >).insert(std::declval< value_type && >)))> insert(value_type &&value)
Definition: observed_value.hpp:888
reference front()
Definition: observed_value.hpp:741
iterator erase(iterator pos)
Definition: observed_value.hpp:963
Detail::PickFirst_t< void, decltype(std::declval< U >).reserve(std::declval< std::size_t >)))> reserve(size_type capacity)
Definition: observed_value.hpp:848
const_reverse_iterator rend() const noexcept
Definition: observed_value.hpp:819
typename ContainerT::allocator_type allocator_type
Definition: observed_value.hpp:637
void insertRangeChecked(std::size_t low, std::size_t high, RangeOperationType type)
Definition: observed_value.hpp:1126
const_reference back() const
Definition: observed_value.hpp:753
typename ContainerT::const_pointer const_pointer
Definition: observed_value.hpp:643
Detail::PickFirst_t< void, decltype(std::declval< U >).resize(std::declval< std::size_t >), std::declval< value_type const & >)))> resize(size_type count, value_type const &fillValue)
Definition: observed_value.hpp:1077
const_iterator end() const noexcept
Definition: observed_value.hpp:795
auto registerAfterEffect()
Definition: observed_value.hpp:1170
Detail::PickFirst_t< void, decltype(std::declval< U >).resize(std::declval< std::size_t >)))> resize(size_type count)
Definition: observed_value.hpp:1056
EventContext::EventIdType afterEffectId_
Definition: observed_value.hpp:1197
ObservedContainer(CustomEventContextFlag_t, EventContext *ctx, T &&t)
Definition: observed_value.hpp:665
iterator end() noexcept
Definition: observed_value.hpp:791
reference at(size_type pos)
Definition: observed_value.hpp:765
ObservedContainer & operator=(const ObservedContainer &)=delete
reverse_iterator rend() noexcept
Definition: observed_value.hpp:815
const_reference operator[](size_type pos) const
Definition: observed_value.hpp:777
iterator insert(iterator pos, value_type &&value)
Definition: observed_value.hpp:909
reference back()
Definition: observed_value.hpp:749
const_pointer data() const noexcept
Definition: observed_value.hpp:761
iterator insert(const_iterator pos, value_type &&value)
Definition: observed_value.hpp:913
void assign(std::initializer_list< value_type > ilist)
Definition: observed_value.hpp:733
void assign(Iterator first, Iterator last)
Definition: observed_value.hpp:727
ObservedContainer & operator=(ObservedContainer &&)=default
ObservedContainer & operator=(T &&t)
Definition: observed_value.hpp:713
iterator begin() noexcept
Definition: observed_value.hpp:783
const_reverse_iterator rbegin() const noexcept
Definition: observed_value.hpp:811
constexpr auto map(auto &&function) const
Definition: range.hpp:153
ObservedContainer(RangeEventContext &&rangeContext)
Definition: observed_value.hpp:676
pointer data() noexcept
Definition: observed_value.hpp:757
const_reverse_iterator crbegin() const noexcept
Definition: observed_value.hpp:823
const_iterator begin() const noexcept
Definition: observed_value.hpp:787
iterator insert(const_iterator pos, const value_type &value)
Definition: observed_value.hpp:902
ObservedContainer(ObservedContainer &&)=default
Detail::PickFirst_t< void, decltype(std::declval< U >).push_front(std::declval< const value_type & >)))> push_front(const value_type &value)
Definition: observed_value.hpp:1013
typename ContainerT::size_type size_type
Definition: observed_value.hpp:638
ObservedContainer(T &&t, RangeEventContext &&rangeContext)
Definition: observed_value.hpp:687
iterator insert(const_iterator pos, std::initializer_list< value_type > ilist)
Definition: observed_value.hpp:948
Detail::PickFirst_t< std::size_t, decltype(std::declval< U >).capacity())> capacity() const noexcept
Definition: observed_value.hpp:853
Detail::PickFirst_t< std::size_t, decltype(std::declval< U >).max_size())> max_size() const noexcept
Definition: observed_value.hpp:842
iterator insert(const_iterator pos, Iterator first, Iterator last)
Definition: observed_value.hpp:937
Detail::PickFirst_t< void, decltype(std::declval< U >).push_back(std::declval< value_type >)))> push_back(value_type &&value)
Definition: observed_value.hpp:1006
ObservedContainer(const ObservedContainer &)=delete
iterator erase(const_iterator pos)
Definition: observed_value.hpp:971
void emplace_back(Args &&... args)
Definition: observed_value.hpp:1026
const_reverse_iterator crend() const noexcept
Definition: observed_value.hpp:827
typename ContainerT::value_type value_type
Definition: observed_value.hpp:636
void update(bool force=false) const override
Definition: observed_value.hpp:1117
iterator insert(const_iterator pos, size_type count, const value_type &value)
Definition: observed_value.hpp:924
Detail::PickFirst_t< void, decltype(std::declval< U >).emplace_front())> emplace_front(Args &&... args)
Definition: observed_value.hpp:1032
reference operator[](size_type pos)
Definition: observed_value.hpp:773
iterator emplace(const_iterator pos, Args &&... args)
Definition: observed_value.hpp:956
void pop_back()
Definition: observed_value.hpp:1037
Detail::PickFirst_t< std::pair< typename ContainerT::iterator, bool >, decltype(std::declval< U >).insert(std::declval< const value_type & >)))> insert(const value_type &value)
Definition: observed_value.hpp:874
Detail::PickFirst_t< void, decltype(std::declval< U >).push_front(std::declval< value_type >)))> push_front(value_type &&value)
Definition: observed_value.hpp:1020
const_iterator cend() const noexcept
Definition: observed_value.hpp:803
iterator insert(iterator pos, Iterator first, Iterator last)
Definition: observed_value.hpp:932
reverse_iterator rbegin() noexcept
Definition: observed_value.hpp:807
Detail::PickFirst_t< void, decltype(std::declval< U >).pop_front())> pop_front()
Definition: observed_value.hpp:1046
const_iterator cbegin() const noexcept
Definition: observed_value.hpp:799
typename ContainerT::const_reverse_iterator const_reverse_iterator
Definition: observed_value.hpp:649
void assign(size_type count, const value_type &value)
Definition: observed_value.hpp:720
typename ContainerT::const_iterator const_iterator
Definition: observed_value.hpp:646
iterator erase(iterator first, iterator last)
Definition: observed_value.hpp:979
ObservedContainer(T &&t)
Definition: observed_value.hpp:671
bool empty() const noexcept
Definition: observed_value.hpp:833
ContainerT & value()
Definition: observed_value.hpp:1099
void eraseNotify(std::size_t index, std::size_t high)
Definition: observed_value.hpp:1184
MoveDetector moveDetector_
Definition: observed_value.hpp:1195
std::size_t size() const noexcept
Definition: observed_value.hpp:837
Detail::PickFirst_t< void, decltype(std::declval< U >).push_back(std::declval< const value_type & >)))> push_back(const value_type &value)
Definition: observed_value.hpp:999
typename ContainerT::difference_type difference_type
Definition: observed_value.hpp:639
RangeEventContext & rangeContext()
Definition: observed_value.hpp:1107
typename ContainerT::const_reference const_reference
Definition: observed_value.hpp:641
iterator insert(iterator pos, size_type count, const value_type &value)
Definition: observed_value.hpp:920
ObservedContainer(CustomEventContextFlag_t, EventContext *ctx, T &&t, RangeEventContext &&rangeContext)
Definition: observed_value.hpp:693
void clear()
Definition: observed_value.hpp:864
ContainerT const & value() const
Definition: observed_value.hpp:1103
RangeEventContext const & rangeContext() const
Definition: observed_value.hpp:1111
iterator insert(iterator pos, const value_type &value)
Definition: observed_value.hpp:898
Detail::PickFirst_t< void, decltype(std::declval< U >).shrink_to_fit())> shrink_to_fit()
Definition: observed_value.hpp:858
Observed< std::basic_string< Parameters... > > & operator=(std::basic_string< Parameters... > const &contained)
Definition: observed_value.hpp:1268
Observed< std::basic_string< Parameters... > > & erase(std::size_t index=0, std::size_t count=std::string::npos)
Definition: observed_value.hpp:1279
Observed< std::basic_string< Parameters... > > & operator=(std::basic_string< Parameters... > &&contained)
Definition: observed_value.hpp:1273
Observed< std::deque< Parameters... > > & operator=(std::deque< Parameters... > &&contained)
Definition: observed_value.hpp:1253
Observed< std::deque< Parameters... > > & operator=(std::deque< Parameters... > const &contained)
Definition: observed_value.hpp:1248
Observed()
Definition: observed_value.hpp:1330
Observed< std::list< Parameters... > > & operator=(std::list< Parameters... > const &contained)
Definition: observed_value.hpp:1338
Observed(T &&t)
Definition: observed_value.hpp:1334
Observed< std::list< Parameters... > > & operator=(std::list< Parameters... > &&contained)
Definition: observed_value.hpp:1343
Observed(T &&t)
Definition: observed_value.hpp:1305
Observed< std::set< Parameters... > > & operator=(std::set< Parameters... > &&contained)
Definition: observed_value.hpp:1314
Observed< std::set< Parameters... > > & operator=(std::set< Parameters... > const &contained)
Definition: observed_value.hpp:1309
Observed()
Definition: observed_value.hpp:1301
Observed< std::vector< Parameters... > > & operator=(std::vector< Parameters... > &&contained)
Definition: observed_value.hpp:1233
Observed< std::vector< Parameters... > > & operator=(std::vector< Parameters... > const &contained)
Definition: observed_value.hpp:1228
Definition: observed_value.hpp:1352
void modify() const
Definition: observed_value.hpp:1357
void modifyNow() const
Definition: observed_value.hpp:1362
Definition: observed_value.hpp:1202
Observed & operator=(T const &contained)
Definition: observed_value.hpp:1208
Observed & operator=(T &&contained)
Definition: observed_value.hpp:1213
Definition: range_event_context.hpp:187
auto & unwrapReferenceWrapper(ReferenceWrapper< T, ContainerT > &wrapper)
Definition: observed_value.hpp:433
typename ObservedAddReference< std::decay_t< T > >::type ObservedAddReference_t
Definition: observed_value.hpp:1545
typename PickFirst< Ts... >::type PickFirst_t
Definition: pick_first.hpp:22
typename ObservedAddMutableReference< std::remove_reference_t< T > >::type ObservedAddMutableReference_t
Definition: observed_value.hpp:1547
typename ObservedAddMutableReference< std::remove_reference_t< T > >::raw ObservedAddMutableReference_raw
Definition: observed_value.hpp:1549
Definition: file_dialog.hpp:6
typename UnpackObserved< T >::type UnpackObserved_t
Definition: observed_value.hpp:1583
concept IsSharedObserved
Definition: observed_value.hpp:1453
concept IsObserved
Definition: observed_value.hpp:1451
requires Incrementable< T > ModifiableObserved< T > & operator++(ModifiableObserved< T > &observedValue)
Definition: observed_value.hpp:1416
RangeOperationType
Definition: range_event_context.hpp:17
@ Modify
Definition: range_event_context.hpp:19
@ Insert
Definition: range_event_context.hpp:20
@ Erase
Definition: range_event_context.hpp:21
thread_local EventContext globalEventContext
Definition: event_context.cpp:5
requires(IsObservedLike< ObservedValues > &&...) ObservedValueCombinator< std
Definition: observed_value_combinator.hpp:191
auto operator--(ModifiableObserved< T > &observedValue) -> ModifiableObserved< Detail::PickFirst_t< T, decltype(--std::declval< T >())>> &
Definition: observed_value.hpp:1433
emscripten::val val
Definition: val.hpp:5
concept IsWeakObserved
Definition: observed_value.hpp:1455
constexpr CustomEventContextFlag_t CustomEventContextFlag
Definition: observed_value.hpp:27
concept IsObservedLike
Definition: observed_value.hpp:1457
Definition: observed_value.hpp:26
Definition: observed_value.hpp:1463
constexpr CopyableObservedWrap(Observed< T > const &observed)
Definition: observed_value.hpp:1465
void detachEvent(auto eventId) const
Definition: observed_value.hpp:1479
T const & value() const
Definition: observed_value.hpp:1469
void attachEvent(auto eventId) const
Definition: observed_value.hpp:1474
Definition: observed_value.hpp:1408
Definition: observed_value.hpp:1372
Definition: observed_value.hpp:1396
Definition: observed_value.hpp:1384
std::weak_ptr< Observed< T > > type
Definition: observed_value.hpp:1540
std::weak_ptr< Observed< T > > type
Definition: observed_value.hpp:1534
void raw
Definition: observed_value.hpp:1529
void type
Definition: observed_value.hpp:1528
Definition: observed_value.hpp:1521
T raw
Definition: observed_value.hpp:1523
T & type
Definition: observed_value.hpp:1522
std::weak_ptr< Observed< T > > type
Definition: observed_value.hpp:1506
std::weak_ptr< const Observed< T > > type
Definition: observed_value.hpp:1516
std::weak_ptr< Observed< T > > type
Definition: observed_value.hpp:1501
std::weak_ptr< const Observed< T > > type
Definition: observed_value.hpp:1511
void type
Definition: observed_value.hpp:1496
Definition: observed_value.hpp:1490
T const & type
Definition: observed_value.hpp:1491
T type
Definition: observed_value.hpp:1560
T type
Definition: observed_value.hpp:1570
T type
Definition: observed_value.hpp:1565
Definition: observed_value.hpp:1554
T type
Definition: observed_value.hpp:1555