mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-16 22:53:34 +08:00
dsdlc: union tag enumeration; improved is()/as()/to() with support for either direct access via StorageType, or indirect access via Spec type
This commit is contained in:
@@ -59,6 +59,16 @@ struct UAVCAN_EXPORT ${t.cpp_type_name}
|
||||
${expand_attr_types(group_name='FieldTypes', attrs=fields)}
|
||||
|
||||
% if union:
|
||||
|
||||
struct Tag
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
% for idx,a in enumerate(fields):
|
||||
${a.name}${',' if idx < (len(fields) - 1) else ''}
|
||||
% endfor
|
||||
};
|
||||
};
|
||||
|
||||
typedef IntegerSpec< ::uavcan::IntegerBitLen< ${len(fields)} >::Result,
|
||||
::uavcan::SignednessUnsigned, ::uavcan::CastModeTruncate > TagType;
|
||||
@@ -150,12 +160,49 @@ public:
|
||||
::uavcan::TailArrayOptimizationMode tao_mode = ::uavcan::TailArrayOptEnabled);
|
||||
|
||||
% if union:
|
||||
/**
|
||||
* Constructors and assignment operators will only work if T is unique within the union; otherwise
|
||||
* compilation will fail with an error referring to ambiguous template instantiation.
|
||||
*/
|
||||
template <typename T>
|
||||
${type_name}(const T& x)
|
||||
% for idx,a in enumerate(fields):
|
||||
${':' if idx == 0 else ','} ${a.name}()
|
||||
% endfor
|
||||
% if union:
|
||||
, _tag_()
|
||||
% endif
|
||||
{
|
||||
to<T>() = x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
${type_name}& operator=(const T& x)
|
||||
{
|
||||
to<T>() = x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use explicit tag access if the union contains non-unique types.
|
||||
* Otherwise it is safer to use as<>(), to<>(), is<>().
|
||||
*/
|
||||
typename Tag::Type getTag() const { return Tag::Type(_tag_); }
|
||||
void setTag(typename Tag::Type x) { _tag_ = ::uavcan::StorageType< TagType >::Type(x); }
|
||||
|
||||
/**
|
||||
* Whether the union is set to the given type.
|
||||
* Access by type; this will only work if the type is unique within the union; otherwise compilation will fail.
|
||||
*/
|
||||
template <typename T>
|
||||
bool is() const;
|
||||
|
||||
/**
|
||||
* Whether the union is set to the given type.
|
||||
* Access by tag; this will work even if there are non-unique types within the union.
|
||||
*/
|
||||
bool is(typename Tag::Type x) const { return Tag::Type(_tag_) == x; }
|
||||
|
||||
/**
|
||||
* If the union is currently set to the type T, returns pointer to the appropriate field.
|
||||
* If the union is set to another type, returns null pointer.
|
||||
@@ -328,32 +375,49 @@ ${generate_codec_calls_per_field(call_name='encode', self_parameter_type='Parame
|
||||
${generate_codec_calls_per_field(call_name='decode', self_parameter_type='ReferenceType')}
|
||||
|
||||
% if union:
|
||||
template <>
|
||||
template <typename T>
|
||||
typename ::uavcan::EnableIfType< typename T::StorageType, bool>::Type ${scope_prefix}<0>::is() const
|
||||
{
|
||||
return is<typename T::StorageType>();
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename T>
|
||||
typename ::uavcan::EnableIfType< typename T::StorageType, const typename T::StorageType*>::Type
|
||||
${scope_prefix}<0>::as() const
|
||||
{
|
||||
return as<typename T::StorageType>();
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename T>
|
||||
typename ::uavcan::EnableIfType< typename T::StorageType, typename T::StorageType&>::Type
|
||||
${scope_prefix}<0>::to()
|
||||
{
|
||||
return to<typename T::StorageType>();
|
||||
}
|
||||
|
||||
% for idx,a in enumerate(fields):
|
||||
template <>
|
||||
template <>
|
||||
bool ${scope_prefix}<0>::is< typename ${scope_prefix}<0>::FieldTypes::${a.name} >() const
|
||||
bool ${scope_prefix}<0>::is< typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type >() const
|
||||
{
|
||||
return _tag_ == ${idx};
|
||||
}
|
||||
|
||||
% endfor
|
||||
|
||||
% for idx,a in enumerate(fields):
|
||||
template <>
|
||||
template <>
|
||||
const typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type*
|
||||
${scope_prefix}<0>::as< typename ${scope_prefix}<0>::FieldTypes::${a.name} >() const
|
||||
${scope_prefix}<0>::as< typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type >() const
|
||||
{
|
||||
return is< typename FieldTypes::${a.name} >() ? &${a.name} : NULL;
|
||||
return is< typename ${scope_prefix}<0>::FieldTypes::${a.name} >() ? &${a.name} : NULL;
|
||||
}
|
||||
|
||||
% endfor
|
||||
|
||||
% for idx,a in enumerate(fields):
|
||||
template <>
|
||||
template <>
|
||||
typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type&
|
||||
${scope_prefix}<0>::to< ${scope_prefix}<0>::FieldTypes::${a.name} >()
|
||||
${scope_prefix}<0>::to< typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type >()
|
||||
{
|
||||
if (_tag_ != ${idx})
|
||||
{
|
||||
@@ -368,8 +432,10 @@ ${scope_prefix}<0>::to< ${scope_prefix}<0>::FieldTypes::${a.name} >()
|
||||
<!--(end)-->
|
||||
|
||||
% if t.kind == t.KIND_SERVICE:
|
||||
${define_out_of_line_struct_methods(scope_prefix=t.cpp_type_name + '::Request_', fields=t.request_fields, union=t.request_union)}
|
||||
${define_out_of_line_struct_methods(scope_prefix=t.cpp_type_name + '::Response_', fields=t.response_fields, union=t.response_union)}
|
||||
${define_out_of_line_struct_methods(scope_prefix=t.cpp_type_name + '::Request_', fields=t.request_fields, \
|
||||
union=t.request_union)}
|
||||
${define_out_of_line_struct_methods(scope_prefix=t.cpp_type_name + '::Response_', fields=t.response_fields, \
|
||||
union=t.response_union)}
|
||||
% else:
|
||||
${define_out_of_line_struct_methods(scope_prefix=t.cpp_type_name, fields=t.fields, union=t.union)}
|
||||
% endif
|
||||
|
||||
Reference in New Issue
Block a user