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

T

A Tag type. If omitted, T defaults to default_tag.

E

An Entity type, for Tag T.

ET

Traits of E for Tag T.

e

An object of type E

Entity Requirements

Name

Expression

Result Type

Semantics

Entity Traits

traits_of<E, T>::type

ET

The Traits of Entity E for Tag T.

Entity Concept Check

is_entity<E, T>::type

Boolean MPL Metafunction that evaulates to true

Concept check for the Entity concept.

Traits Requirements

Name

Expression

Result Type

Semantics

Tag

ET::tag

T

The Tag for ET.

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 ));