COMMS
Template library intended to help with implementation of communication protocols.
Classes | Namespaces | Macros
Field.h File Reference

Contains definition of comms::Field class. More...

#include <type_traits>
#include "comms/util/access.h"
#include "comms/details/FieldBase.h"
#include "comms/details/macro_common.h"
#include "comms/details/fields_access.h"
#include "comms/details/field_alias.h"

Go to the source code of this file.

Classes

class  comms::Field< TOptions >
 Base class to all the field classes. More...
 

Namespaces

 comms
 Main namespace for all classes / functions of COMMS library.
 

Macros

#define COMMS_FIELD_ALIAS(f_, ...)   COMMS_DO_ALIAS(field_, f_, __VA_ARGS__)
 Generate convinience alias access member functions for other member fields. More...
 
#define COMMS_FIELD_MEMBERS_ACCESS(...)
 Add convenience access enum and functions to the members of composite fields, such as comms::field::Bundle or comms::field::Bitfield. More...
 
#define COMMS_FIELD_MEMBERS_ACCESS_NOTEMPLATE(...)
 Similar to COMMS_FIELD_MEMBERS_ACCESS(), but dedicated for non-template classes. More...
 
#define COMMS_FIELD_MEMBERS_NAMES(...)
 Provide names for member fields of composite fields, such as comms::field::Bundle or comms::field::Bitfield. More...
 

Detailed Description

Contains definition of comms::Field class.

Macro Definition Documentation

◆ COMMS_FIELD_ALIAS

#define COMMS_FIELD_ALIAS (   f_,
  ... 
)    COMMS_DO_ALIAS(field_, f_, __VA_ARGS__)

Generate convinience alias access member functions for other member fields.

Same as COMMS_MSG_FIELD_ALIAS() but applicable to comms::field::Bundle field.

Precondition
The macro COMMS_FIELD_MEMBERS_ACCESS() needs to be used before COMMS_FIELD_ALIAS() to define convenience access functions.

◆ COMMS_FIELD_MEMBERS_ACCESS

#define COMMS_FIELD_MEMBERS_ACCESS (   ...)
Value:
COMMS_EXPAND(COMMS_DEFINE_FIELD_ENUM(__VA_ARGS__)) \
COMMS_FIELD_VALUE_ACCESS_FUNC { \
auto& val = comms::field::toFieldBase(*this).value(); \
using AllFieldsTuple = typename std::decay<decltype(val)>::type; \
static_assert(std::tuple_size<AllFieldsTuple>::value == FieldIdx_numOfValues, \
"Invalid number of names for fields tuple"); \
return val; \
} \
COMMS_FIELD_VALUE_ACCESS_CONST_FUNC { \
auto& val = comms::field::toFieldBase(*this).value(); \
using AllFieldsTuple = typename std::decay<decltype(val)>::type; \
static_assert(std::tuple_size<AllFieldsTuple>::value == FieldIdx_numOfValues, \
"Invalid number of names for fields tuple"); \
return val; \
} \
COMMS_EXPAND(COMMS_DO_FIELD_ACC_FUNC(ValueType, value(), __VA_ARGS__))
Bundle< TFieldBase, TMembers, TOptions... > & toFieldBase(Bundle< TFieldBase, TMembers, TOptions... > &field)
Upcast type of the field definition to its parent comms::field::Bundle type in order to have access t...
Definition: Bundle.h:805

Add convenience access enum and functions to the members of composite fields, such as comms::field::Bundle or comms::field::Bitfield.

Very similar to COMMS_FIELD_MEMBERS_NAMES(), but does NOT require definition of Base inner member type (for some compilers) and does NOT define inner Field_* types for used member fields.

Parameters
[in]...List of fields' names.
See also
COMMS_FIELD_MEMBERS_NAMES()
Note
Relevant to comms::field::Bundle and comms::field::Bitfield
Defined in "comms/Field.h"
Warning
Some compilers, such as clang or early versions of g++ may have problems compiling code generated by this macro even though it uses valid C++11 constructs in attempt to automatically identify the type of the base class. If the compilation fails, and this macro resides inside a NON-template class, please use COMMS_FIELD_MEMBERS_ACCESS_NOTEMPLATE() macro instead. In case this macro needs to reside inside a template class, then there is still a need to define inner Base type, which specifies exact type of the comms::field::Bitfield or comms::field::Bundle class.
template <typename... TExtraOptions>
class MyField : public
MyFieldBase,
std::tuple<Field1, Field2, Field3>,
TExtraOptions...
>
{
// Define type of the base class
using Base =
MyFieldBase,
std::tuple<Field1, Field2, Field3>,
TExtraOptions...
>;
public:
COMMS_FIELD_MEMBERS_ACCESS(member1, member2, member3);
};
#define COMMS_FIELD_MEMBERS_ACCESS(...)
Add convenience access enum and functions to the members of composite fields, such as comms::field::B...
Definition: Field.h:236
Bitfield field.
Definition: Bitfield.h:98

◆ COMMS_FIELD_MEMBERS_ACCESS_NOTEMPLATE

#define COMMS_FIELD_MEMBERS_ACCESS_NOTEMPLATE (   ...)
Value:
COMMS_EXPAND(COMMS_DEFINE_FIELD_ENUM(__VA_ARGS__)) \
COMMS_EXPAND(COMMS_DO_FIELD_ACC_FUNC_NOTEMPLATE(__VA_ARGS__))

Similar to COMMS_FIELD_MEMBERS_ACCESS(), but dedicated for non-template classes.

The COMMS_FIELD_MEMBERS_ACCESS() macro is a generic one, which can be used in any class (template, or non-template). However, some compilers (such as g++-4.9 and below, clang-4.0 and below) may fail to compile it even though it uses valid C++11 constructs. If the compilation fails and the class it is being used in is NOT a template one, please use COMMS_FIELD_MEMBERS_ACCESS_NOTEMPLATE() instead.

See also
COMMS_FIELD_MEMBERS_NAMES()
COMMS_FIELD_MEMBERS_ACCESS()
Note
Defined in "comms/Field.h"

◆ COMMS_FIELD_MEMBERS_NAMES

#define COMMS_FIELD_MEMBERS_NAMES (   ...)
Value:
COMMS_EXPAND(COMMS_FIELD_MEMBERS_ACCESS(__VA_ARGS__)) \
COMMS_EXPAND(COMMS_DO_FIELD_TYPEDEF(typename Base::ValueType, Field_, FieldIdx_, __VA_ARGS__))

Provide names for member fields of composite fields, such as comms::field::Bundle or comms::field::Bitfield.

The fields of "composite" types, such as comms::field::Bundle or comms::field::Bitfield keep their members bundled in std::tuple and provide access to them via value() member functions. The access to the specific member field can be obtained using std::get later on:

using Field1 = ... /* some field definition */;
using Field2 = ... /* some field definition */;
using Field3 = ... /* some field definition */;
using MyField =
MyFieldBase,
std::tuple<Field1, Field2, Field3>
>;
MyField field;
auto& members = field.value();
auto& firstMember = std::get<0>(members);
auto& secondMember = std::get<1>(members);
auto& thirdMember = std::get<2>(members);
Base class to all the field classes.
Definition: Field.h:33
const ValueType & value() const
Get access to the stored tuple of fields.
Definition: Bitfield.h:194

However, it would be convenient to provide names and easier access to the member fields. The COMMS_FIELD_MEMBERS_NAMES() macro does exactly that when used inside the field class definition. Just inherit from the "composite" field and use the macro inside with the names for the member fields:

class MyField : public comms::field::Bitfield<...>
{
// (Re)define base class as inner Base type, required by COMMS_FIELD_MEMBERS_NAMES()
using Base = comms::field::Bitfield<...>;
public:
COMMS_FIELD_MEMBERS_NAMES(member1, member2, member3);
}
#define COMMS_FIELD_MEMBERS_NAMES(...)
Provide names for member fields of composite fields, such as comms::field::Bundle or comms::field::Bi...
Definition: Field.h:380

NOTE that there is a required to have Base member type that specifies base class used.

Usage of the COMMS_FIELD_MEMBERS_NAMES() is equivalent to having the following types and functions definitions:

class MyField : public comms::field::Bitfield<...>
{
public:
// Access indices for member fields
enum FieldIdx {
FieldIdx_member1,
FieldIdx_member2,
FieldIdx_member3,
FieldIdx_numOfValues
};
// Accessor to "member1" member field.
auto field_member1() -> decltype(std::get<FieldIdx_member1>(value()))
{
return std::get<FieldIdx_member1>(value());
}
// Accessor to const "member1" member field.
auto field_member1() const -> decltype(std::get<FieldIdx_member1>(value()))
{
return std::get<FieldIdx_member1>(value());
}
// Accessor to "member2" member field.
auto field_member2() -> decltype(std::get<FieldIdx_member2>(value()))
{
return std::get<FieldIdx_member2>(value());
}
// Accessor to const "member2" member field.
auto field_member2() const -> decltype(std::get<FieldIdx_member2>(value()))
{
return std::get<FieldIdx_member2>(value());
}
// Accessor to "member3" member field.
auto field_member3() -> decltype(std::get<FieldIdx_member2>(value()))
{
return std::get<FieldIdx_member3>(value());
}
// Accessor to const "member3" member field.
auto field_member2() const -> decltype(std::get<FieldIdx_member3>(value()))
{
return std::get<FieldIdx_member3>(value());
}
// Redefinition of the field types:
using Field_member1 = Field1;
using Field_member2 = Field2;
using Field_member3 = Field3;
};

NOTE, that provided names member1, member2, and member3, have found their way to the following definitions:

  • FieldIdx enum. The names are prefixed with FieldIdx_. The FieldIdx_nameOfValues value is automatically added at the end.
  • Accessor functions prefixed with field_*
  • Types of fields prefixed with Field_*

See Bitfield Fields and Bundle Fields for more examples and details

Parameters
[in]...List of member fields' names.
Note
Defined in "comms/Field.h"