Zusätzlich zu der anderen Diskussion hier, ist es vielleicht erwähnenswert, dass man Globalität haben kann, ohne die Verwendung auf eine Instanz zu beschränken. Betrachten wir zum Beispiel den Fall der Referenzzählung von etwas...
struct Store{
std::array<Something, 1024> data;
size_t get(size_t idx){ /* ... */ }
void incr_ref(size_t idx){ /* ... */}
void decr_ref(size_t idx){ /* ... */}
};
template<Store* store_p>
struct ItemRef{
size_t idx;
auto get(){ return store_p->get(idx); };
ItemRef() { store_p->incr_ref(idx); };
~ItemRef() { store_p->decr_ref(idx); };
};
Store store1_g;
Store store2_g; // we don't restrict the number of global Store instances
Nun wird irgendwo innerhalb einer Funktion (z. B. main
) können Sie tun:
auto ref1_a = ItemRef<&store1_g>(101);
auto ref2_a = ItemRef<&store2_g>(201);
Die Schiedsrichter müssen keinen Zeiger zurück auf ihre jeweiligen Store
weil diese Information zur Kompilierzeit bereitgestellt wird. Sie müssen sich auch nicht um die Store
Lebensdauer, weil der Compiler verlangt, dass sie global ist. Wenn es tatsächlich nur eine Instanz von Store
dann gibt es bei diesem Ansatz keinen Overhead; bei mehr als einer Instanz ist es Sache des Compilers, bei der Codegenerierung clever vorzugehen. Falls nötig, kann der ItemRef
Klasse kann sogar zu einer friend
von Store
(Sie können Freunde mit Schablonen haben!).
Si Store
selbst eine Vorlagenklasse ist, werden die Dinge unübersichtlicher, aber es ist immer noch möglich, diese Methode zu verwenden, vielleicht durch die Implementierung einer Hilfsklasse mit der folgenden Signatur:
template <typename Store_t, Store_t* store_p>
struct StoreWrapper{ /* stuff to access store_p, e.g. methods returning
instances of ItemRef<Store_t, store_p>. */ };
Der Benutzer kann nun eine StoreWrapper
Typ (und globale Instanz) für jede globale Store
Instanz, und greifen Sie immer über ihre Wrapper-Instanz auf die Speicher zu (und vergessen Sie dabei die blutigen Details der Vorlagenparameter, die für die Verwendung von Store
).