C++ Concepts¶
Concepts are used to provide the template meta-programming information
about the intented use of a type. For example, concepts::is_component<T>::value
is used
to test whether the type T
is a component and thus, should be continue to
try to provide some functionality for that component. In general, each concept::is_<CONCEPT>
can be activated by inheriting from concepts::<CONCEPT>
. Every concept can be
activated or deactivated by specializing
concept::is_<CONCEPT>
to inherit from std::true_type
or std::false_type
, respectively.
When available, timemory uses the inheritance method so that down-stream users can
perform a template specialization (which overrides the inheritance) is the need arises.
Inheritable Concepts¶
-
template<typename
Tp
>
structis_empty
¶ concept that specifies that a variadic type is empty
-
template<typename
Tp
>
structis_null_type
¶ concept that specifies that a type is not a useful type
-
template<typename
Tp
>
structis_placeholder
¶ concept that specifies that a type is not necessarily marked as not available but is still a dummy type
-
template<typename
Tp
>
structis_component
¶ concept that specifies that a type is a component. Components are used to perform some measurement, capability, or logging implementation. Adding this concept can be performs through inheriting from tim::component::base, inheriting from tim::concepts::component, or specializing either tim::concepts::is_component or tim::trait::is_component (with the latter being deprecated).
-
template<typename
Tp
>
structis_quirk_type
¶ concept that specifies that a type is a quirk. Quirks are used to modify the traditional behavior of component bundles slightly. E.g. disable calling start in the constructor of an auto_tuple.
-
template<typename
Tp
>
structis_api
¶ concept that specifies that a type is an API. APIs are used to designate different project implementations, different external library tools, etc.
-
template<typename
Tp
>
structis_variadic
¶ concept that specifies that a type is a generic variadic wrapper
-
template<typename
Tp
>
structis_wrapper
¶ concept that specifies that a type is a timemory variadic wrapper
-
template<typename
Tp
>
structis_stack_wrapper
¶ concept that specifies that a type is a timemory variadic wrapper and components are stack-allocated
-
template<typename
Tp
>
structis_heap_wrapper
¶ concept that specifies that a type is a timemory variadic wrapper and components are heap-allocated
-
template<typename
Tp
>
structis_mixed_wrapper
¶ concept that specifies that a type is a timemory variadic wrapper and variadic types are mix of stack- and heap- allocated
-
template<typename
Tp
>
structis_tagged
¶ concept that specifies that a type’s template parameters include a API specific tag as one of the template parameters (usually first)
-
template<typename
Tp
>
structis_comp_wrapper
¶ concept that specifies that a type is a timemory variadic wrapper that does not perform auto start/stop, e.g. component_{tuple,list,hybrid}
-
template<typename
Tp
>
structis_auto_wrapper
¶ concept that specifies that a type is a timemory variadic wrapper that performs auto start/stop, e.g. auto_{tuple,list,hybrid}
-
template<typename
Tp
>
structis_runtime_configurable
¶ concept that specifies that a type is used to modify behavior at runtime. For example, the tim::component::user_bundle component is runtime configurable bc it allows you insert components at runtime. The timing category (
tim::category::timing
) is another example of a type that is runtime configurable settingtim::trait::runtime_enabled<tim::category::timing>::set(false);
will disable (at runtime) all the types which are part of the timing API. It should be noted that types which satisfyis_runtime_configurable<Tp>::value == true
(e.g. tim::component::user_bundle) are not eligible to be inserted into other runtime configurable components; i.e. you cannot insert/add tim::component::user_trace_bundle into tim::component::user_global_bundle, etc. This restriction is primarily due to the significant increase in compile-time that arises from allowing this behavior.
-
template<typename
Tp
>
structis_external_function_wrapper
¶ concept that specifies that a component type wraps external functions
-
template<typename
Tp
>
structis_phase_id
¶ concept that specifies that a type is used for identifying a phase in some measurement. For example,
tim::audit::incoming
andtim::audit::outgoing
can be added to overloads to distinguish whether thedouble
type indouble exp(double val)
isval
or whether it is the return value.struct exp_wrapper_A { // unable to distingush whether "val" is input or output void audit(double val) { ... } }; struct exp_wrapper_B { // able to distingush whether "val" is input or output void audit(audit::incoming, double val) { ... } void audit(audit::outgoing, double val) { ... } };
Non-Inheritable Concepts¶
-
template<typename
Lhs
, typenameRhs
>
structis_acceptable_conversion
¶ This concept designates that is safe to perform a
static_cast<Lhs>(rhs)
where needed. This is primarily used in the tim::component::data_tracker wheredata_tracker<unsigned int, ...>
might be provided another integral type, such asint
.- tparam Lhs
the provided type
- tparam Rhs
the target type
-
template<typename
T
>
structtuple_type
¶ This concept is used to express how to convert a given type into a
std::tuple
, e.g.tim::component_tuple<T...>
tostd::tuple<T...>
. It is necessary for types like tim::component_bundle where certain template parameters are tags.
-
template<typename
T
>
structauto_type
¶ This concept is used to express how to convert a component bundler into another component bundler which performs automatic starting upon construction.
-
template<typename
T
>
structcomponent_type
¶ This concept is used to express how to convert a component bundler which automatically starts upon construction into a type that requires an explicit call to start.