11#pragma once
22
33#include < StormByte/exception.hxx>
4+ #include < StormByte/type_traits.hxx>
45
56#include < iterator>
67#include < utility>
@@ -307,18 +308,18 @@ namespace StormByte {
307308 */
308309 iterator begin () noexcept { return iterator (m_data.begin ()); }
309310
310- /* *
311- * @brief Gets end iterator
312- * @return Iterator to the end of the container
313- */
314- iterator end () noexcept { return iterator (m_data.end ()); }
315-
316311 /* *
317312 * @brief Gets const begin iterator
318313 * @return Const iterator to the beginning of the container
319314 */
320315 const_iterator begin () const noexcept { return const_iterator (m_data.begin ()); }
321316
317+ /* *
318+ * @brief Gets end iterator
319+ * @return Iterator to the end of the container
320+ */
321+ iterator end () noexcept { return iterator (m_data.end ()); }
322+
322323 /* *
323324 * @brief Gets const end iterator
324325 * @return Const iterator to the end of the container
@@ -390,33 +391,186 @@ namespace StormByte {
390391 * @param i Index of the element to access
391392 * @return Reference to the element at index i
392393 */
393- reference operator [](size_type i) {
394+ reference operator [](size_type i)
395+ requires Type::HasSubscript<Container, size_type> {
394396 if (i >= m_data.size ())
395397 throw OutOfBoundsError (" Index {} out of bounds in Iterable::operator[]" , i);
396398 return m_data[i];
397399 }
398400
401+ reference operator [](size_type i)
402+ requires (!Type::HasSubscript<Container, size_type>) {
403+ if (i >= m_data.size ())
404+ throw OutOfBoundsError (" Index {} out of bounds in Iterable::operator[]" , i);
405+ auto it = m_data.begin ();
406+ std::advance (it, i);
407+ return *it;
408+ }
409+
410+ /* *
411+ * @brief Access element at given index (non-const version)
412+ * @param i Index of the element to access
413+ * @return Reference to the element at index i
414+ * @note This overload is for when container does not support operator[] or mapped_type
415+ */
416+ auto operator [](size_type i) -> decltype (auto )
417+ requires (!Type::HasSubscript<Container, size_type> && !Type::HasMappedType<Container>) {
418+ if (i >= m_data.size ())
419+ throw OutOfBoundsError (" Index {} out of bounds in Iterable::operator[]" , i);
420+ auto it = m_data.begin ();
421+ std::advance (it, i);
422+ return *it;
423+ }
424+
425+
426+ /*
427+ * @brief Key-based access for associative containers (non-const)
428+ * @param key The key to access in the underlying container
429+ * @return Reference to the mapped value (forward to container's operator[])
430+ */
431+ template <typename K>
432+ auto operator [](K const &key) -> decltype (auto )
433+ requires (Type::HasMappedType<Container>) {
434+ return m_data[static_cast <typename Container::key_type>(key)];
435+ }
436+
437+ /*
438+ * @brief Key-based access for associative containers (const)
439+ * @param key The key to access in the underlying container
440+ * @return Const reference to the mapped value (searches and throws if not found)
441+ */
442+ template <typename K>
443+ auto operator [](K const &key) const -> decltype (auto )
444+ requires (Type::HasMappedType<const Container>) {
445+ auto k = static_cast <typename Container::key_type>(key);
446+ auto it = m_data.find (k);
447+ if (it == m_data.cend ())
448+ throw OutOfBoundsError (" Key not found in Iterable::operator[]" );
449+ return it->second ;
450+ }
451+
399452 /* *
400453 * @brief Access element at given index (const version)
401454 * @param i Index of the element to access
402455 * @return Const reference to the element at index i
403456 */
404- const_reference operator [](size_type i) const {
457+ const_reference operator [](size_type i) const
458+ requires Type::HasSubscript<const Container, size_type> {
405459 if (i >= m_data.size ())
406460 throw OutOfBoundsError (" Index {} out of bounds in Iterable::operator[]" , i);
407461 return m_data[i];
408462 }
409463
464+ /* *
465+ * @brief Access element at given index (const version)
466+ * @param i Index of the element to access
467+ * @return Const reference to the element at index i
468+ * @note This overload is for when container does not support operator[] or mapped_type
469+ */
470+ const_reference operator [](size_type i) const
471+ requires (!Type::HasSubscript<const Container, size_type>) {
472+ if (i >= m_data.size ())
473+ throw OutOfBoundsError (" Index {} out of bounds in Iterable::operator[]" , i);
474+ auto it = m_data.cbegin ();
475+ std::advance (it, i);
476+ return *it;
477+ }
478+
479+ /* *
480+ * @brief Access element at given index (const version)
481+ * @param i Index of the element to access
482+ * @return Const reference to the element at index i
483+ * @note This overload is for when container does not support operator[] or mapped_type
484+ */
485+ auto operator [](size_type i) const -> decltype (auto )
486+ requires (!Type::HasSubscript<const Container, size_type> && !Type::HasMappedType<const Container>) {
487+ if (i >= m_data.size ())
488+ throw OutOfBoundsError (" Index {} out of bounds in Iterable::operator[]" , i);
489+ auto it = m_data.cbegin ();
490+ std::advance (it, i);
491+ return *it;
492+ }
493+
494+ /* *
495+ * @brief Adds an element to the container
496+ * @param value The element to add
497+ */
498+ void add (const value_type& value) requires Type::HasPushBack<decltype(m_data)> {
499+ m_data.push_back (value);
500+ }
501+
410502 /* *
411503 * @brief Adds an element to the container
412504 * @param value The element to add
413505 */
414- void add (const value_type& value) { m_data.push_back (value); }
506+ void add (const value_type& value) requires (!Type::HasPushBack<decltype (m_data)> and Type::HasPushFront<decltype(m_data)>) {
507+ m_data.push_front (value);
508+ }
509+
510+ /* *
511+ * @brief Adds an element to associative containers via `insert`
512+ */
513+ void add (const value_type& value) requires (!Type::HasPushBack<decltype (m_data)> and !Type::HasPushFront<decltype(m_data)> and Type::HasInsert<decltype(m_data)>) {
514+ m_data.insert (value);
515+ }
516+
517+ /* *
518+ * @brief Adds an element to the container (move version)
519+ * @param value The element to add
520+ */
521+ void add (value_type&& value) requires Type::HasPushBack<decltype(m_data)> {
522+ m_data.push_back (std::move (value));
523+ }
415524
416525 /* *
417526 * @brief Adds an element to the container (move version)
418527 * @param value The element to add
419528 */
420- void add (value_type&& value) { m_data.push_back (std::move (value)); }
421- };
529+ void add (value_type&& value) requires (!Type::HasPushBack<decltype (m_data)> and Type::HasPushFront<decltype(m_data)>) {
530+ m_data.push_front (std::move (value));
531+ }
532+
533+ /* *
534+ * @brief Adds an element to associative containers via `insert` (move version)
535+ */
536+ void add (value_type&& value) requires (!Type::HasPushBack<decltype (m_data)> and !Type::HasPushFront<decltype(m_data)> and Type::HasInsert<decltype(m_data)>) {
537+ m_data.insert (std::move (value));
538+ }
539+
540+ /* *
541+ * @brief Checks if the container has a specific item
542+ * @param value The item to check for
543+ * @return True if the item exists in the container, false otherwise
544+ */
545+ bool has_item (const value_type& value) const {
546+ for (const auto & item : m_data) {
547+ if (item == value) {
548+ return true ;
549+ }
550+ }
551+ return false ;
552+ }
553+
554+ template <typename M>
555+ bool has_item (M const &value) const
556+ requires Type::HasMappedType<const Container> && std::convertible_to<M, typename Container::mapped_type> {
557+ for (const auto &item : m_data) {
558+ if (item.second == value) return true ;
559+ }
560+ return false ;
561+ }
562+
563+ /* *
564+ * @brief Checks if the container has a specific key (for associative containers)
565+ * @param key The key to check for
566+ * @return True if the key exists in the container, false otherwise
567+ */
568+ template <typename K>
569+ bool has_key (const K& key) const
570+ requires Type::HasMappedType<const Container> {
571+ auto k = static_cast <typename Container::key_type>(key);
572+ return m_data.find (k) != m_data.cend ();
573+
574+ }
575+ };
422576}
0 commit comments