27namespace sequoia::object
30 template<std::input_or_output_iterator Iterator>
34 using value_type =
typename std::iterator_traits<Iterator>::value_type;
35 using reference = std::string;
44 constexpr static reference get(Iterator i)
65 template<
class... Products>
66 requires (
sizeof...(Products) > 0) && (std::movable<Products> && ...)
70 using key = std::string;
71 using vessel = std::variant<Products...>;
74 constexpr static std::size_t size()
noexcept
76 return sizeof...(Products);
80 template<
class Product>
83 using creator_variant = std::variant<product_creator<Products>...>;
84 using element = std::pair<key, creator_variant>;
85 using storage = std::array<element, size()>;
86 using const_storage_iterator =
typename storage::const_iterator;
91 requires (has_extrinsic_nomenclator<Products> && ...)
95 template<
class... Names>
96 requires (
sizeof...(Names) == size()) && (std::is_constructible_v<std::string, Names> && ...)
98 : m_Creators{make_element<Products>(std::move(names))...}
100 std::ranges::sort(m_Creators, [](
const element& lhs,
const element& rhs){
return lhs.first < rhs.first; });
102 auto comp{[](
const element& lhs,
const element& rhs) {
return lhs.first == rhs.first; }};
103 if(std::ranges::adjacent_find(m_Creators, comp) != m_Creators.cend())
104 throw std::logic_error{
"Factory product names must be unique!"};
107 template<
class... Args>
110 vessel make(std::string_view name, Args&&... args)
const
112 const auto found{find(name)};
114 if(found == m_Creators.end())
115 throw std::runtime_error{std::string{
"Factory unable to make product of name '"}.append(name).append(
"'")};
117 return std::visit(
overloaded{[&](
const auto& v) {
return vessel{v.make(std::forward<Args>(args)...)}; }}, found->second);
120 template<
class Product,
class... Args>
121 requires ( (std::is_same_v<Product, Products> || ...)
124 vessel make_or(std::string_view name, Args&&... args)
const
126 auto found{find(name)};
127 if(found == m_Creators.end())
129 found = std::ranges::find_if(m_Creators, [](
const element& e){
return std::holds_alternative<product_creator<Product>>(e.second); });
132 return std::visit(
overloaded{[&](
const auto& v) {
return vessel{v.make(std::forward<Args>(args)...)}; }}, found->second);
136 friend bool operator==(
const factory&,
const factory&)
noexcept =
default;
150 storage m_Creators{};
153 auto find(std::string_view name)
const
155 const auto found{std::ranges::lower_bound(m_Creators, name, std::ranges::less{}, [](
const element& e){
return e.first; })};
157 return (found != m_Creators.end()) && (found->first == name) ? found : m_Creators.end();
160 template<
class Product>
162 static element make_element(std::string name)
165 throw std::logic_error{
"Factory product names must not be empty!"};
Concepts which are sufficiently general to appear in the sequoia namespace.
Traits, Concepts and basic utilities for the creation of objects.
Implementation for an iterator with policies controlling dereferencing and auxiliary data.
Utilities for associating types with names.
Meta-programming utilities.
Policy to allow iteration over the names of factory products.
Definition: Factory.hpp:32
Generic factory with statically defined products.
Definition: Factory.hpp:68
Creates a product for T.
Definition: Creator.hpp:74
An iterator with policies controlling dereferencing and auxiliary data.
Definition: Iterator.hpp:234
A concept similar to std::constructible_from, but which considers braced-init.
Definition: Concepts.hpp:75
Definition: Nomenclator.hpp:31
Definition: Utilities.hpp:73