13 template <
typename SYMBOL_PROVIDER>
17 using internal_value_type =
typename symbol_provider::internal_value_type;
18 using hash_type =
typename symbol_provider::hash_type;
20 internal_value_type value = symbol_provider::empty_value();
22 explicit symbol_base(std::string_view
val) : value{ symbol_provider::insert(
val) } { }
25 hash_type get_hash()
const noexcept {
return symbol_provider::hash_for(value); }
26 std::string_view get_string()
const noexcept {
return symbol_provider::string_for(value); }
27 explicit operator std::string_view()
const noexcept {
return symbol_provider::string_for(value); }
31 bool operator==(symbol_base
const&
other)
const noexcept {
return value ==
other.value || symbol_provider::compare(value,
other.value) == 0; }
32 auto operator<=>(symbol_base
const&
other)
const noexcept {
return symbol_provider::compare(value,
other.value); }
34 friend bool operator==(std::string_view a, symbol_base
const& b)
noexcept {
return a == b.get_string(); }
35 friend auto operator<=>(std::string_view a, symbol_base
const& b)
noexcept {
return a <=> b.get_string(); }
37 friend std::ostream& operator<<(std::ostream&
o,
const symbol_base&
ptr)
39 o <<
ptr.get_string();
45template <
typename SYMBOL_PROVIDER>
46struct std::hash<
ghassanpl::symbol_base<SYMBOL_PROVIDER>> {
54 concept symbol_provider =
57 typename T::internal_value_type;
58 typename T::hash_type;
59 { T::empty_value() }
noexcept -> std::same_as<typename T::internal_value_type>;
60 { T::insert(std::string_view{}) } -> std::same_as<typename T::internal_value_type>;
61 { T::string_for(
typename T::internal_value_type{}) }
noexcept -> std::same_as<std::string_view>;
62 { T::hash_for(
typename T::internal_value_type{}) }
noexcept -> std::same_as<typename T::hash_type>;
63 { T::compare(
typename T::internal_value_type{},
typename T::internal_value_type{}) }
noexcept -> std::same_as<std::strong_ordering>;
65 && std::three_way_comparable<typename T::internal_value_type>
66 && std::regular<typename T::internal_value_type>
69 template <
typename TAG =
void>
70 struct default_symbol_provider_t
72 static default_symbol_provider_t& instance()
noexcept
74 static default_symbol_provider_t
inst;
78 using internal_value_type = std::string
const*;
80 static internal_value_type empty_value()
noexcept {
return instance().m_empty_string; }
81 static internal_value_type insert(std::string_view
val)
86 auto& values = instance().m_values;
87 if (
auto v = values.find(
val); v == values.end())
88 return &*values.insert(std::string{
val }).
first;
92 static std::string_view string_for(internal_value_type
val)
noexcept {
return val ? std::string_view{ *
val } : std::string_view{}; }
93 static hash_type hash_for(internal_value_type
val)
noexcept {
return std::hash<const void*>{}(
val); }
95 static std::strong_ordering compare(internal_value_type a, internal_value_type b)
noexcept {
96 return (a == b) ? std::strong_ordering::equal : (*
a <=> *b);
104 m_values.insert(std::string{});
105 m_empty_string = &*m_values.begin();
112 auto empty_string()
const noexcept {
return m_empty_string; }
116 std::set<std::string, std::less<>> m_values{ std::string{} };
117 std::string
const* m_empty_string = &*m_values.begin();
120 using default_symbol_provider = default_symbol_provider_t<void>;
121 using symbol = symbol_base<default_symbol_provider>;
constexpr auto bit_count
Equal to the number of bits in the type.
Primary namespace for everything in this library.