lager::
deps
¶Dependency passing type.
This type helps passing contextual dependencies arround. Effectively, it is a bag of statically keyed values (dependencies). You can convert between bags of dependencies, as long as the required dependencies of the target bag is a strict subset of the required dependencies of the argument bag. They idea is that a the root of your application you hold a bag with all the context you need. You pass this context around to various components, each extracting a subset of it. Components can further down pass these extracting further subsets.
Another way to look at it is that deps
is basically like a struct where naming members is optional, and where you can automatically convert between structs that have attributes with the same name. In type theortical terms, this way of converting between types is called structural typing.
Here is one example of how this type might be used.
struct user_db_t {};
struct post_db_t {};
void foo(deps<dep::key<user_db, database&>, dep::opt<logger&>> d)
{
database& db = d.get<user_db>();
db.write(...);
if (d.has<logger>()) d.get<logger>().debug("...");
}
void bar(deps<logger&, dep::opt<dep::key<post_db, database&>> d)
{
try {
d.get<logger>().info("", d.get<post_db>().query(...));
} catch (missing_dependency const&) {
// d.get<post_db>() may throw cuz it's optional
}
}
int main()
{
database udb;
database pdb;
logger log;
auto dependencies = deps<dep::key<user_db, database&>,
dep::key<post_db, database&>
logger&>::from(udb, pdb, log);
foo(dependencies);
bar(dependencies);
}
Deps dependency specifications for each attribute of deps
.
dep::to_spec
. lager::
make_deps
(Ts&&... args)¶Returns a deps object containing everything passed in args
. Dependencies will be stored as references only if wrapped in a std::reference_wrapper
(see std::ref
).
is_spec = std::is_base_of<spec, T>
to_spec = typename std::conditional_t< is_spec_v<T>, T, std::conditional_t<std::is_reference_v<T> || detail::is_reference_wrapper_v<T>, ref<std::remove_reference_t<T>>, val<T>>>::type
Convert T
to a dependency specification. If T
is a dependency specification it just returns T
. If T
is a reference type or a std::reference_wrapper
, it results in a ref<[dereferenced T]>
. Otherwise it is just a val<T>
.
lager::dep::
is_spec_v
= is_spec<T>::value¶lager::dep::
as
(typename Spec::storage v)¶Pairs value of type T with specificatio Spec
lager::dep::
fn
¶Modifies specification or type T
to make it indirectly provided via a function.
lager::dep::
key
¶Modifies specification or type T
to associate it with type tag K
.
lager::dep::
opt
¶Modifies specification or type T
to make it optional.
lager::dep::
ref
¶Specify a dependency of references to T and key T
Inherits from lager::dep::spec
Subclassed by lager::dep::ref< std::reference_wrapper< T > >
lager::dep::
ref
<std::reference_wrapper<T>>¶Inherits from lager::dep::ref< T >
lager::dep::
spec
¶Base class that marks specification types.
Subclassed by lager::dep::ref< T >, lager::dep::val< T >
lager::dep::
val
¶Specify a dependency of value T and key T
Inherits from lager::dep::spec
decltype(auto) lager::get(const deps< Ts... > & d)
Free standing alias for deps::get()
lager::
has
(const deps<Ts...> &d)¶Free standing alias for deps::has()
lager::
is_deps
¶Metafunction to see if something is a deps type.