Entity
is a base concept for Ports
and Components.
Every Entity
has an associated Traits
type which describes it's dataflow properties. The examples below show
how Traits
can be registered for an Entity.
The registration of an Entity
with a Traits
is always for a specific Tag.
Hence, a type is an Entity
only relative to a Tag,
and can have different Traits
for different Tags.
Refinements
Notation
Entity Requirements
|
Name |
Expression |
Result Type |
Semantics |
|---|---|---|---|
|
Entity Traits |
|
|
|
|
Entity Concept Check |
|
Boolean MPL Metafunction that evaulates to true |
Concept check for the |
Traits Requirements
|
Name |
Expression |
Result Type |
Semantics |
|---|---|---|---|
|
Tag |
|
|
The
|
Header
The types, templates, and functions shown here are declared in the following files:
#include <boost/dataflow/support.hpp>
Notes
There is an intrusive as well as a non-intrusive way to register the
Traits
of a type E, thereby
making it an Entity.
Non-intrusive registration is typically done by providing a specialization
of the register_traits
template (either directly, or through the provided macros DATAFLOW_TRAITS and DATAFLOW_TRAITS_ENABLE_IF).
This will specialize traits_of
for all cv-qualified versions of type E.
If cv-qualified versions of type E
should have different Traits,
traits_of should
be specialized directly.
Intrusive registration can be done by providing a E::dataflow_traits
member type, which can be either a Traits
type, or an MPL sequence of Traits
types. Alternatively, the Dataflow library provides a convenience class
entity which you can
inherit instead of declaring the member type. This provides the additional
benefit of being able to access free functions in the boost::dataflow
namespace using ADL.
The below examples illustrate the avaliable registration methods.
Examples
All of the below examples use the following Tag
and Traits
types:
typedef df::port_traits<df::ports::producer> producer_traits; typedef df::port_traits<df::ports::consumer> consumer_traits; struct some_tag : public df::default_tag {}; typedef df::port_traits<df::ports::consumer, some_tag> other_consumer_traits;
Intrusive registration
Intrusive registration is the easiest, but assumes you can modify the
Entity:
// Intrusive registration of a single port struct intrusive_producer_port { // intrusive_producer_port is a ProducerPort typedef producer_traits dataflow_traits; }; // Intrusive registration of a multiple ports struct intrusive_producer_consumer_port { // intrusive_producer_port is a ProducerPort for the default_tag, // and a ConsumerPort for some_tag typedef boost::mpl::vector<producer_traits, other_consumer_traits> dataflow_traits; };
Non-intrusive registration
Non-intrusive registration is done by specializing the register_traits template. Since the
register_traits template
is keyed by Tag,
this is rather verbose:
struct non_intrusive_port { // Can't or don't want to modify the type }; namespace boost { namespace dataflow { // register_traits holds the PortTraits type of a Port template<> struct register_traits<non_intrusive_port> { typedef producer_traits type; }; } } // namespace boost::dataflow
To make things simpler, the Dataflow library provides a macro for non-intrusive
registration (the macro also performs a static concept check on the
Traits).
// Non-intrusive registration via a macro: struct non_intrusive_port2 { // Can't or don't want to modify the type }; DATAFLOW_TRAITS(non_intrusive_port2, producer_traits)
Non-intrusive mass registration
The register_traits
template has an Enable template parameter for use with boost::enable_if. Hence, we can register a
number of types at the same time:
// Non-intrusive registration via an enable_if expression struct non_intrusive_port_base { }; namespace boost { namespace dataflow { // register_traits holds the PortTraits type of a Port template<typename T> struct register_traits< T, default_tag, typename boost::enable_if< boost::is_base_of<non_intrusive_port_base, T> >::type> { typedef producer_traits type; }; } } // namespace boost::dataflow struct non_intrusive_port_descendant : public non_intrusive_port_base {};
And again, there is a convenient macro:
// Non-intrusive registration via a macro and an enable_if expression struct non_intrusive_port_base2 { }; DATAFLOW_TRAITS_ENABLE_IF( T, boost::is_base_of<non_intrusive_port_base2 BOOST_PP_COMMA() T>, producer_traits) struct non_intrusive_port_descendant2 : public non_intrusive_port_base2 {};
Tests
With the above registrations, the following tests pass:
BOOST_CHECK(( df::is_port<intrusive_producer_port>::value )); BOOST_CHECK(( df::is_port<intrusive_producer_consumer_port, some_tag>::value )); BOOST_CHECK(( df::is_port<non_intrusive_port>::value )); BOOST_CHECK(( df::is_port<non_intrusive_port2>::value )); BOOST_CHECK(( df::is_port<non_intrusive_port_descendant>::value )); BOOST_CHECK(( df::is_port<non_intrusive_port_descendant2>::value ));