xentara-plugin v2.0.4
The Xentara Plugin Framework
Loading...
Searching...
No Matches
xentara::config::CustomResolver< Reference > Class Template Reference

A resolver for resolving custom cross references during loading. More...

#include <xentara/config/CustomResolver.hpp>

+ Inheritance diagram for xentara::config::CustomResolver< Reference >:

Classes

class  Committer
 Object for custom handling. More...
 
struct  NameProjection
 A projection that gets the name of an object using name() More...
 

Public Member Functions

 CustomResolver (std::string_view unknownObjectMessageFormat)
 Constructor that uses a format string for error messages.
 
 CustomResolver (std::string &&)=delete
 Deleted constructor that prevents accidentally using a temporary std::string as unknown object message format.
 
Resolving cross references
template<std::invocable< Reference > Handler>
auto resolve (Context::ReferenceKey key, Handler handler) -> void
 Submits a request to resolve a cross reference.
 
template<typename Variable >
requires std::is_assignable_v<Variable &, Reference>
auto resolve (Context::ReferenceKey key, std::reference_wrapper< Variable > variable) -> void
 Submits a request to resolve a cross reference and assign it to a variable.
 

Handling submitted requests

template<std::ranges::input_range Map>
requires requires(Map &objects, std::string_view key) { { objects.find(key)->second } -> std::convertible_to<Reference>; }
auto commit (Map &objects)
 Handles all the submitted requests using a map-like collection.
 
template<std::ranges::input_range Range>
auto commit (Range &objects)
 Handles all the submitted requests using an arbitrary collection.
 
template<std::input_iterator Iterator, std::sentinel_for< Iterator > Sentinel>
auto commit (Iterator first, Sentinel last)
 Handles all the submitted requests using a pair of arbitrary iterators.
 
template<typename KeyProjection , std::ranges::input_range Range>
auto commit (Range &objects, KeyProjection keyProjection={})
 Handles all the submitted requests using an arbitrary collection using a custom key projection.
 
template<typename KeyProjection , std::input_iterator Iterator, std::sentinel_for< Iterator > Sentinel>
auto commit (Iterator first, Sentinel last, KeyProjection keyProjection={})
 Handles all the submitted requests using a pair of arbitrary iterators.
 

Detailed Description

template<typename Reference>
class xentara::config::CustomResolver< Reference >

A resolver for resolving custom cross references during loading.

You can use this class to resolve reference between objects in the configuration of an element without having to worry about the order in which the objects appear in the model file. The resolver works similar to the resolving facility in the Context class.

To resolve custom references in a load callback, create a CustomResolver before loading the configuration parameters. Submit requests to the resolver as necessary, as you would with Context::resolve(). After all the parameters have been loaded, call commit() to resolve the cross-references.

Example:

auto MyElement::load(utils::json::decoder::Object &jsonObject, config::Context &context) -> void
{
CustomResolver<std::reference_wrapper<MyTargetObject>> targetObjectResolver { R"(unknown target object "{}")"sv };
for (auto &&[name, value] : jsonObject)
{
// TODO: loading the actual target objects and placing them in the collection "_targetObjects"
// TODO: call targetObjectResolver.resolve() as necessary to submit requests to resolve references
}
targetObjectResolver.commit(_targetObjects);
}
A context used when loading skill elements.
Definition Context.hpp:56
A resolver for resolving custom cross references during loading.
Definition CustomResolver.hpp:62
auto commit(Map &objects)
Handles all the submitted requests using a map-like collection.
Definition CustomResolver.hpp:375
Template Parameters
ReferenceThe type of reference passed to the resolve callback or assigned to the resolve variable. This can either be an std::reference_wrapper, an std::shared_ptr, an std::weak_ptr, or another reference or pointer-like type. It can also be a raw pointer or a raw reference.
Attention
Do not use the plain object type as a template parameter, as this will cause the object to be passed to the callback by value. Instread, use Object & or const Object & as reference type.

Constructor & Destructor Documentation

◆ CustomResolver() [1/2]

template<typename Reference >
xentara::config::CustomResolver< Reference >::CustomResolver ( std::string_view  unknownObjectMessageFormat)
explicit

Constructor that uses a format string for error messages.

Parameters
unknownObjectMessageFormatAn std::format-compatible format string for the error message to output if an object is not found. The string should contain one substitution field (“{}”) that will be replaced with the name of the object that was not found. The format string must remain valid for entire lifetime of the resolver.

◆ CustomResolver() [2/2]

template<typename Reference >
xentara::config::CustomResolver< Reference >::CustomResolver ( std::string &&  )
delete

Deleted constructor that prevents accidentally using a temporary std::string as unknown object message format.

Member Function Documentation

◆ commit() [1/5]

template<typename Reference >
template<std::input_iterator Iterator, std::sentinel_for< Iterator > Sentinel>
auto xentara::config::CustomResolver< Reference >::commit ( Iterator  first,
Sentinel  last 
)

Handles all the submitted requests using a pair of arbitrary iterators.

This function handles all the requests submitted using resolve() by iterating over an arbitrary range.

The lookup keys of the objects are extracted by trying to call a function called name() on the iterator elements. The elements must therefore support exactly one of the following function calls:

  • element.name()
  • element->name()
  • element.get().name()

This allows this function to get the name from references, raw pointers, smart pointers, as well as std::reference_wrapper and compatible types.

Parameters
firstAn iterator to the first eligible target object.
lastA sentinel pointing to the position past the end of the eligible target objects.

◆ commit() [2/5]

template<typename Reference >
template<typename KeyProjection , std::input_iterator Iterator, std::sentinel_for< Iterator > Sentinel>
auto xentara::config::CustomResolver< Reference >::commit ( Iterator  first,
Sentinel  last,
KeyProjection  keyProjection = {} 
)

Handles all the submitted requests using a pair of arbitrary iterators.

This function handles all the requests submitted using resolve() by iterating over an arbitrary range.

To allow the function to extract the keys from the entries, you must specify a key projection. The key projection must be function-like object that returns the key when passed a reference to an object. The default key projection looks for a function called name() to get the key. The name() function is called in one of the following ways, whichever is supported:

  • reference.name()
  • reference->name()
  • reference.get().name()

The lookup keys of the objects are extracted using a key projection. The key projection must be function-like object that returns the key when passed a const reference to an iterator element.

Parameters
firstAn iterator to the first eligible target object.
lastA sentinel pointing to the position past the end of the eligible target objects.
keyProjectionA function-like object that can be used to extract the key from the objects. The projection will be called using std::invoke(keyProjection, *iterator) to get the keys for the individual objects.

◆ commit() [3/5]

template<typename Reference >
requires requires(Map &objects, std::string_view key) { { objects.find(key)->second } -> std::convertible_to<Reference>; }
template<std::ranges::input_range Map>
requires requires(Map &objects, std::string_view key) { { objects.find(key)->second } -> std::convertible_to<Reference>; }
auto xentara::config::CustomResolver< Reference >::commit ( Map &  objects)

Handles all the submitted requests using a map-like collection.

This function handles all the requests submitted using resolve() by looking up the relevant objects in a map-like collection, like std::unordered_map or std::map. The collection must have a find() function that can be passed an std::string_view as the key to look up the object. The function must return an std::pair of key and value analogous to std::unordered_map::find() and std::map::find().

◆ commit() [4/5]

template<typename Reference >
template<std::ranges::input_range Range>
auto xentara::config::CustomResolver< Reference >::commit ( Range &  objects)

Handles all the submitted requests using an arbitrary collection.

This function handles all the requests submitted using resolve() by iterating over objects in an arbitrary collection, like std::vector or std::list.

The lookup keys of the objects are extracted by trying to call a function called name() on the range elements. The elements must therefore support exactly one of the following function calls:

  • element.name()
  • element->name()
  • element.get().name()

This allows this function to get the name from references, raw pointers, smart pointers, as well as std::reference_wrapper and compatible types.

Parameters
objectsThe eligible target objects.

◆ commit() [5/5]

template<typename Reference >
template<typename KeyProjection , std::ranges::input_range Range>
auto xentara::config::CustomResolver< Reference >::commit ( Range &  objects,
KeyProjection  keyProjection = {} 
)

Handles all the submitted requests using an arbitrary collection using a custom key projection.

This function handles all the requests submitted using resolve() by iterating over objects in an arbitrary collection, like std::vector or std::list.

The lookup keys of the objects are extracted using a key projection. The key projection must be function-like object that returns the key when passed a const reference to a range element.

Parameters
objectsThe eligible target objects.
keyProjectionA function-like object that can be used to extract the key from the objects. The projection will be called using std::invoke(keyProjection, *constRangeIterator) to get the keys for the individual objects.

◆ resolve() [1/2]

template<typename Reference >
template<std::invocable< Reference > Handler>
auto xentara::config::CustomResolver< Reference >::resolve ( Context::ReferenceKey  key,
Handler  handler 
) -> void

Submits a request to resolve a cross reference.

This function submits a request to resolve a cross reference using the given key. When commit() is called, the given handler will be called as if by:

Reference reference = resolveReferenceInSomeMysteriousWay(key);
handler(reference);

To submit a request to resolve an object by calling a member function called setTargetObject(), for example, you can use the following code:

customContext.resolve(key, [this](std::reference_wrapper<MyTargetObject> object)
{
setTargetObject(object);
});
Parameters
keyThe key of the object to resolve
handlerThe handler that should be called once the reference has been resolved. The handler must remain valid during the entire lifetime of the resolver.

◆ resolve() [2/2]

template<typename Reference >
requires std::is_assignable_v<Variable &, Reference>
template<typename Variable >
requires std::is_assignable_v<Variable &, Reference>
auto xentara::config::CustomResolver< Reference >::resolve ( Context::ReferenceKey  key,
std::reference_wrapper< Variable >  variable 
) -> void

Submits a request to resolve a cross reference and assign it to a variable.

This function submits a request to resolve a cross reference using the given key. When commit() is called, the resolved reference will be assigned to a variable as if by:

Reference reference = resolveReferenceInSomeMysteriousWay(key);
variable.get() = reference;

To submit a request to resolve an object and store it in a member variable named *_targetObject*, for example, you can use the following code:

customContext.resolve(key, std::ref(_targetObject));
T ref(T... args)
Parameters
keyThe primary key of the object to resolve
variableA reference to the variable the resolved object should be assigned to. To enable the compiler to select the correct overload, you should pass this parameter using std::ref. The handler must remain valid during the entire lifetime of the resolver.