Query Objects#
Warning
This page is for amongoc
developers and the documented components and
behavior are not part of any public API guarantees.
The C++ components contain query objects, which generalize the idea of getters to invocables that can look up attributes of another object.
A query object \(Q\) can be invoked on an object to be queried: \(Q(x)\), which will return the value associated with attribute \(Q\) on \(x\), if such an attribute is available.
-
class get_allocator_fn#
-
class get_stop_token_fn#
Look up the allocator or the stop token associated with an object, if one is available. These classes have an overloaded
operator()
method that allows them to be used as function objects.For a query object \(Q\) of type
get_xyz_fn
, the overloadedoperator()
does the following when passed an object \(x\):If \(x\) has a method
get_xyz()
, returns the result of that function.Otherwise, if \(x\) has a method
query()
that accepts an instance ofget_xyz_fn
, returns the result ofquery(Q)
.Otherwise, the overloaded
operator()
is not available.
-
inline constexpr get_allocator_fn get_allocator#
-
inline constexpr get_stop_token_fn get_stop_token#
Global instances of the associated query object types.
-
template<typename T>
concept has_allocator# -
template<typename T>
concept has_stop_token# Test whether the associated queries are valid for the type
T
-
template<typename T>
using get_allocator_t# -
template<typename T>
using get_stop_token_t# Get the result type of applying the associated queries.
-
template<typename Q, typename T>
using query_t = decltype(Q{}(std::declval<const T&>()))# Obtains the result of applying query type
Q
to an objectT
. Requires: valid_query_for<Q, T>
-
template<typename Q, typename T>
concept valid_query_for#
Query Forwarding Example#
Suppose we have a function-wrapping type which wraps an invocable and adds the
argument 42
as the last argument when the wrapper is invoked:
template <typename F>
struct also_42 {
F _fn;
auto operator()(auto&&... args) {
return _fn(args..., 42);
}
};
It is possible that F
has attributes that we want to expose on also_42
.
In that case, we would add a query
method template with valid_query_for
:
template <typename F>
struct also_42 {
F _fn;
auto operator()(auto&&... args) {
return _fn(args..., 42);
}
auto query(valid_query_for<F> auto q) const {
return q(_fn);
}
};
This allows any query object that is valid for F
to be applied to
also_42<F>
.
Differences from P2300#
P2300 also defines query objects and query types, but with a few important differences:
Queryable objects in P2300 may define a separate environment object so that their queries can be performed on a separate instance from the underyling object. Our querying code does not use separate environments, as we don’t yet have a need for this. This may be added later if the need arises.
P2300 queries can carry additional arguments to the
query
methods. We don’t yet need this functionality, so it is omitted.