Skip to content

Instantly share code, notes, and snippets.

@TymianekPL
Created September 19, 2024 17:32
Show Gist options
  • Save TymianekPL/e258025c45938fa8fe63bfb4d7849476 to your computer and use it in GitHub Desktop.
Save TymianekPL/e258025c45938fa8fe63bfb4d7849476 to your computer and use it in GitHub Desktop.
#ifndef LOOKUPVECTOR_H
#define LOOKUPVECTOR_H
#include <memory>
#include <vector>
namespace Utilities
{
template<typename T, typename = void>
struct auto_const_reference
{
using type = T;
};
template<typename T>
struct auto_const_reference <T, std::enable_if_t <(sizeof(T) > 16 || !std::is_trivially_copyable_v <T>)> >
{
using type = std::add_lvalue_reference_t <std::add_const_t <T> >;
};
template<typename T>
using auto_const_reference_t = typename auto_const_reference <T>::type;
template<typename T, typename TLook>
concept is_lookable = requires(T&& v) { { v->getIdentifier() } -> std::same_as <TLook>; };
template<typename T, typename TKey>
requires is_lookable <T, TKey> && std::is_copy_assignable_v <T>
class lookup_vector final
{
public:
lookup_vector(void) = default;
lookup_vector(std::initializer_list <T> list) : _value(std::move(list)) {}
lookup_vector(const lookup_vector& other) : _value(other._value) {}
lookup_vector(lookup_vector&& other) noexcept = default;
lookup_vector& operator=(const lookup_vector& other)
{
if (this != &other)
_value = other._value;
return *this;
}
lookup_vector& operator=(lookup_vector&& other) noexcept = default;
~lookup_vector(void) = default;
std::optional <T> get(auto_const_reference_t <TKey> key) const noexcept(std::declval <T>().getIdentifier())
{
for (auto& value : this->_value)
if (value->getIdentifier() == key) return value;
return std::nullopt;
}
std::vector <T>& vector(void) noexcept { return this->_value; }
template<typename TS>
requires std::convertible_to <TS, T>
void push(TS&& value) { _value.push_back(std::forward <TS>(value)); }
bool remove(auto_const_reference_t <TKey> key) noexcept
{
auto it = std::remove_if(this->_value.begin(), this->_value.end(),
[&key](const T& value) { return value->getIdentifier() == key; });
if (it != this->_value.end())
{
this->_value.erase(it, this->_value.end());
return true;
}
return false;
}
std::optional <std::size_t> findIndex(auto_const_reference_t <TKey> key) const noexcept
{
for (std::size_t i = 0; i < this->_value.size(); ++i)
if (this->_value[i]->getIdentifier() == key)
return i;
return std::nullopt;
}
T& operator[](auto_const_reference_t <TKey> key)
{
static_assert(std::is_constructible_v <T, TKey>);
for (auto& value : this->_value)
if (value->getIdentifier() == key) return value;
return _value.push_back(std::forward <T>({}));
}
const T& operator[](auto_const_reference_t <TKey> key) const
{
static_assert(std::is_constructible_v <T, TKey>);
for (auto& value : this->_value)
if (value->getIdentifier() == key) return value;
return _value.push_back(std::forward <T>({}));
}
private:
std::vector <T> _value;
};
} // Utilities
#endif //LOOKUPVECTOR_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment