Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
KeyedCollection_Factory.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Containers_Concrete_KeyedCollection_Factory_h_
5#define _Stroika_Foundation_Containers_Concrete_KeyedCollection_Factory_h_
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <type_traits>
10
11/**
12 * \file
13 */
14
16 template <typename T, typename KEY_TYPE, typename TRAITS>
17 class KeyedCollection;
18}
19
20namespace Stroika::Foundation::Containers::Factory {
21
22 /**
23 * \brief Singleton factory object - Used to create the default backend implementation of a KeyedCollection<> container; typically not called directly
24 *
25 * Note - you can override the underlying factory dynamically by calling KeyedCollection_Factory<T,KEY_TYPE,TRAITS>::Register ().
26 *
27 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
28 */
29 template <typename T, typename KEY_TYPE, typename TRAITS, typename KEY_EQUALS_COMPARER = equal_to<KEY_TYPE>>
31 public:
32 static_assert (not is_reference_v<T> and not is_reference_v<KEY_TYPE> and not is_reference_v<KEY_EQUALS_COMPARER>,
33 "typically if this fails its because a (possibly indirect) caller forgot to use forward<TTT>(), or remove_cvref_t");
34
35 public:
36 /**
37 * The type of object produced by the factory.
38 */
40
41 public:
42 using KeyExtractorType = typename ConstructedType::KeyExtractorType;
43
44 public:
45 /**
46 * Function type to create an ConstructedType object.
47 */
48 using FactoryFunctionType = function<ConstructedType (const KeyExtractorType& keyExtractor, const KEY_EQUALS_COMPARER& keyComparer)>;
49
50 public:
51 /**
52 * Hints can be used in factory constructor to guide the choice of the best container implementation/backend.
53 */
54 struct Hints {
55 /**
56 */
57 optional<bool> fOptimizeForLookupSpeedOverUpdateSpeed;
58 };
59
60 public:
61 /**
62 * Construct a factory for producing new ConstructedType objects. The default is to use whatever was registered with
63 * KeyedCollection_Factory::Register (), but a specific factory can easily be constructed with provided arguments.
64 */
65 constexpr KeyedCollection_Factory ();
66 constexpr KeyedCollection_Factory (const Hints& hints);
68 constexpr KeyedCollection_Factory (const KeyedCollection_Factory&) = default;
69
70 public:
71 /**
72 * This can be called anytime, before main(), or after. BUT - beware, any calls to Register must
73 * be externally synchronized, meaning effectively that they must happen before the creation of any
74 * threads, to be safe. Also note, since this returns a const reference, any calls to Register() after
75 * a call to Default, even if synchronized, is suspect.
76 */
77 static const KeyedCollection_Factory& Default ();
78
79 public:
80 /**
81 * You can call this directly, but there is no need, as the KeyedCollection<T,TRAITS> CTOR does so automatically.
82 */
83 nonvirtual ConstructedType operator() (const KeyExtractorType& keyExtractor, const KEY_EQUALS_COMPARER& keyComparer) const;
84
85 public:
86 /**
87 * Register a default global factory for ConstructedType objects (of the templated type/parameters).
88 * No need to call, typically, as the default factory is generally fine.
89 *
90 * \par Example Usage
91 * \code
92 * KeyedCollection_Factory::Register(KeyedCollection_Factory{KeyedCollection_Factory::Hints{.fOptimizeForLookupSpeedOverUpdateSpeed=true});
93 * KeyedCollection_Factory::Register(); // or use defaults
94 * \endcode
95 *
96 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
97 * BUT - special note/restriction - must be called before any threads call Association_Factory::KeyedCollection_Factory() OR
98 * KeyedCollection_Factory::Default(), which effectively means must be called at the start of main, but before creating any threads
99 * which might use the factory).
100 *
101 * \note this differs markedly from Stroika 2.1, where Register could be called anytime, and was internally synchronized.
102 *
103 * \note If you wanted a dynamically changeable factory (change after main), you could write one yourself with its own internal synchronization,
104 * set the global one here, then perform the changes to its internal structure through another API.
105 */
106 static void Register (const optional<KeyedCollection_Factory>& f = nullopt);
107
108 private:
109 const FactoryFunctionType fFactory_;
110
111 private:
112 // function to assure magically constructed even if called before main
113 static KeyedCollection_Factory& AccessDefault_ ();
114 };
115
116}
117
118/*
119 ********************************************************************************
120 ******************************* Implementation Details *************************
121 ********************************************************************************
122 */
123#include "KeyedCollection_Factory.inl"
124
125#endif /*_Stroika_Foundation_Containers_Concrete_KeyedCollection_Factory_h_ */
Singleton factory object - Used to create the default backend implementation of a KeyedCollection<> c...
nonvirtual ConstructedType operator()(const KeyExtractorType &keyExtractor, const KEY_EQUALS_COMPARER &keyComparer) const
static void Register(const optional< KeyedCollection_Factory > &f=nullopt)
function< ConstructedType(const KeyExtractorType &keyExtractor, const KEY_EQUALS_COMPARER &keyComparer)> FactoryFunctionType
a cross between Mapping<KEY, T> and Collection<T> and Set<T>
typename TRAITS::KeyExtractorType KeyExtractorType