Quantum 3xplorer (Q3)
An AI-native quantum simulation engine
Loading...
Searching...
No Matches
registry.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * Registry — an ordered set of interchangeable implementations, found by name.
5 *
6 * Each plug-in point a build-time add-on can extend keeps one: input formats,
7 * pseudopotential formats, PAW one-centre conventions, volumetric formats.
8 * Core seeds its own entries the first time a registry is used, and an add-on
9 * appends its entries from the registration function every entry point calls
10 * before it reads any input (io/addon_registration.hpp). Nothing registers
11 * itself during static initialisation: the order in which translation units
12 * initialise is unspecified, and a registration that depends on it can
13 * silently drop out of one binary while working in another.
14 *
15 * An entry answers to the names its `names()` returns. The first is canonical,
16 * which is the one usage text and error messages print. A name belongs to one
17 * entry only, so registering a second entry under a taken name throws instead
18 * of shadowing the first.
19 *
20 * Entries keep their registration order — core's first, then each add-on's in
21 * the order the build discovered them — so iteration is deterministic.
22 */
23
24#include <memory>
25#include <stdexcept>
26#include <string>
27#include <utility>
28#include <vector>
29
30namespace q3 {
31
32/// An ordered set of interchangeable implementations of `Entry`, found by name.
33template <typename Entry> class Registry {
34 public:
35 /// Add `entry`; throws std::logic_error when one of its names is already registered.
36 void add(std::unique_ptr<Entry> entry) {
37 for (const std::string& name : entry->names()) {
38 if (find(name) != nullptr)
39 throw std::logic_error("The name '" + name + "' is already registered");
40 }
41 entries_.push_back(std::move(entry));
42 }
43
44 /// The entry answering to `name`, or nullptr when none does.
45 [[nodiscard]] const Entry* find(const std::string& name) const {
46 for (const auto& entry : entries_) {
47 for (const std::string& entry_name : entry->names()) {
48 if (entry_name == name)
49 return entry.get();
50 }
51 }
52 return nullptr;
53 }
54
55 /// Every entry, in registration order.
56 [[nodiscard]] const std::vector<std::unique_ptr<Entry>>& entries() const {
57 return entries_;
58 }
59
60 /**
61 * Every entry's canonical name in registration order, joined by
62 * `separator` — the list a usage line or an "unknown name" error prints.
63 */
64 [[nodiscard]] std::string canonical_names(const std::string& separator) const {
65 std::string joined;
66 for (const auto& entry : entries_) {
67 if (!joined.empty())
68 joined += separator;
69 joined += entry->names().front();
70 }
71 return joined;
72 }
73
74 private:
75 std::vector<std::unique_ptr<Entry>> entries_;
76};
77
78} // namespace q3
An ordered set of interchangeable implementations of Entry, found by name.
Definition registry.hpp:33
std::string canonical_names(const std::string &separator) const
Definition registry.hpp:64
const std::vector< std::unique_ptr< Entry > > & entries() const
Every entry, in registration order.
Definition registry.hpp:56
const Entry * find(const std::string &name) const
The entry answering to name, or nullptr when none does.
Definition registry.hpp:45
void add(std::unique_ptr< Entry > entry)
Add entry; throws std::logic_error when one of its names is already registered.
Definition registry.hpp:36