27 using internal_value_type =
typename symbol_provider::internal_value_type;
28 using hash_type =
typename symbol_provider::hash_type;
30 internal_value_type value = symbol_provider::empty_value();
33 requires std::constructible_from<std::string_view, T> && (!std::same_as<std::remove_cvref_t<T>, symbol_base>)
34 symbol_base(T&& val) : value{ symbol_provider::insert(std::forward<T>(val)) } { }
37 requires std::constructible_from<std::string_view, T> && (!std::same_as<std::remove_cvref_t<T>, symbol_base>)
38 symbol_base&
operator=(T&& val)
noexcept { value = symbol_provider::insert(std::forward<T>(val));
return *
this; }
40 symbol_base()
noexcept =
default;
42 symbol_base(symbol_base
const& other)
noexcept =
default;
43 symbol_base(symbol_base&& other)
noexcept =
default;
44 symbol_base& operator=(symbol_base
const& other)
noexcept =
default;
45 symbol_base& operator=(symbol_base&& other)
noexcept =
default;
47 [[nodiscard]] hash_type get_hash()
const noexcept {
return symbol_provider::hash_for(value); }
48 [[nodiscard]] std::string_view get_string()
const noexcept {
return symbol_provider::string_for(value); }
49 [[nodiscard]]
explicit operator std::string_view()
const noexcept {
return symbol_provider::string_for(value); }
50 [[nodiscard]]
explicit operator std::string()
const noexcept {
return std::string{ get_string() }; }
51 [[nodiscard]]
auto to_string()
const noexcept {
return std::string{ get_string() }; }
55 requires requires { { std::to_address(value) } -> meets<std::is_pointer>; }
56 {
return std::to_address(value); }
58 [[nodiscard]]
bool operator==(symbol_base
const& other)
const noexcept {
return value == other.value || symbol_provider::compare(value, other.value) == 0; }
59 [[nodiscard]]
auto operator<=>(symbol_base
const& other)
const noexcept {
return symbol_provider::compare(value, other.value); }
61 [[nodiscard]]
friend bool operator==(std::string_view a, symbol_base
const& b)
noexcept {
return a == b.get_string(); }
62 [[nodiscard]]
friend auto operator<=>(std::string_view a, symbol_base
const& b)
noexcept {
return a <=> b.get_string(); }
66 [[nodiscard]]
bool empty() const noexcept {
return value == symbol_provider::empty_value(); }
67 [[nodiscard]]
size_t size() const noexcept {
return get_string().size(); }
68 friend std::ostream& operator<<(std::ostream& o,
const symbol_base& ptr)
70 o << ptr.get_string();
81 typename T::internal_value_type;
84 typename T::hash_type;
87 { T::empty_value() }
noexcept -> std::same_as<typename T::internal_value_type>;
90 { T::insert(std::string_view{}) } -> std::same_as<typename T::internal_value_type>;
93 { T::string_for(
typename T::internal_value_type{}) }
noexcept -> std::same_as<std::string_view>;
96 { T::hash_for(
typename T::internal_value_type{}) }
noexcept -> std::same_as<typename T::hash_type>;
99 { T::compare(
typename T::internal_value_type{},
typename T::internal_value_type{}) }
noexcept -> std::same_as<std::strong_ordering>;
122 struct default_symbol_provider_t
124 static default_symbol_provider_t& instance()
noexcept
126 static default_symbol_provider_t inst;
130 using internal_value_type = std::string
const*;
131 using hash_type = size_t;
132 [[nodiscard]]
static internal_value_type empty_value()
noexcept {
return instance().m_empty_string; }
133 [[nodiscard]]
static internal_value_type insert(std::string_view val)
136 return empty_value();
138 auto& values = instance().m_values;
139 if (
auto v = values.find(val); v == values.end())
140 return &*values.insert(std::string{ val }).first;
144 [[nodiscard]]
static std::string_view string_for(internal_value_type val)
noexcept {
return val ? std::string_view{ *val } : std::string_view{}; }
145 [[nodiscard]]
static hash_type hash_for(internal_value_type val)
noexcept {
return std::hash<const void*>{}(val); }
147 [[nodiscard]]
static std::strong_ordering compare(internal_value_type a, internal_value_type b)
noexcept {
148 return (a == b) ? std::strong_ordering::equal : (*a <=> *b);
153 void clear()
noexcept
156 auto e = m_values.extract(std::string{});
158 m_values.insert(std::move(e));
161 [[nodiscard]]
size_t size()
const noexcept {
return m_values.size(); }
162 [[nodiscard]]
size_t count()
const noexcept {
return size(); }
164 [[nodiscard]]
auto const& values()
const noexcept {
return m_values; }
165 [[nodiscard]]
auto empty_string()
const noexcept {
return m_empty_string; }
169 std::set<std::string, std::less<>> m_values{ std::string{} };
170 std::string
const* m_empty_string = &*m_values.begin();
172 default_symbol_provider_t() =
default;
173 default_symbol_provider_t(default_symbol_provider_t
const&) =
delete;
174 default_symbol_provider_t& operator=(default_symbol_provider_t
const&) =
delete;