Figure 2: UML class diagram of the proposed containers.
pack, which is a template parameter that accepts zero
or more template arguments (Gregor, 2006). An ellip-
sis following a parameter name defines it as a param-
eter pack. Tuples are data structures which allow to
collect items of different type and access them based
on their defined order.
The order of the elements inside the template con-
sists of taking the current collection type as the first
parameter, and then the related unions’ types. The or-
der is assured to be consistent in the whole generated
model as the Acceleo code generator takes care of
defining it in a query, which always returns the same
output given the same input parameters.
Fig. 2 shows the structure of our realization of the
containers proposed in this paper. Our base data type
is a Set, containing an attribute set (here meant as
a C
++
set) of type T, which is the template type. We
make use of the C
++
templates, which are shown in
angle brackets and separated by commas.
Each Subset then has its type and its set of ele-
ments, of type T, plus one or more unions, of type U.
Each Union contains, in turn, a set, of type U.
There are associations which are at the same time
both a subset and a union. For those cases, the class
SubsetUnion should be used. It takes the same tem-
plate parameters as a Subset but moreover can be ref-
erenced by other subsets, too.
To define the data structures in the metamodel,
the following changes have been performed. The
EReference elements contained in the UML Ecore
metamodel need to be annotated with a defined anno-
tation “union” or “subset” to be interpreted as such
by our C
++
generator. The subset annotation must,
of course, include the referenced union, as the UML
specification does with the <end> attribute inside the
association ends.
With those annotations, the code generator iden-
tifies the unions and subsets. Their types are then
derived from the model, and for each of them an at-
tribute of type Union, Subset or SubsetUnion is cre-
ated in the relevant classes. Moreover, getter methods
are generated for settable references. Those methods,
simply return a shared pointer to the class’ reference
which consists of a ready-to-use list.
4 REALIZATION
All our data structures allow adding, removing and
finding elements contained in them. We use shared
pointers to simplify the memory management.
The Listing 1 shows how the insertion of one ele-
ment in a subset works. As we are using the C
++
Sets
as data structures, it is not needed to check that the
inserted elements are unique. In case the element al-
ready exists in the collection, the element will not be
added again (Musser et al., 2009).
virtual void a dd ( sh ar ed_ pt r <T > el )
{
Set <T >:: add ( el );
call _ a d d E l _ wit h _ t u p l e ( el , _tu pl e ,
inde x _ s e q uen c e _ f o r
< s ha red _p t r < Union < U > > .. . >( )) ;
}
void call _ a d d E l _wit h _ t u p l e (
sh are d_ ptr <T > el ,
const tuple < s h a red _ p tr
< Union < U > >.. . >& tuple ,
in d ex_ s eq u enc e < Is ... >) {
add E l R e cur s i v e ( el ,
get <Is >( t upl e ) . ..) ;
}
template<class Fir st U , class .. . Re stU >
void a d d E l Rec u r s i ve ( s har ed _pt r <T > el ,
sh are d_ ptr < Union < F irstU > > obj ,
sh are d_ ptr < Union < RestU > > . .. rest ) {
add E l R e cur s i v e ( el , re st .. . );
obj -> add ( el );
}
template<class Fir st U , class .. . Re stU >
void a d d E l Rec u r s i ve ( s har ed _pt r <T > el ,
sh are d_ ptr < Union < F irstU > > ob j ) {
obj -> add ( el );
}
Listing 1: add element method of a subset. All operations
are private, except add, which is the public interface.
For brevity, namespaces in listings are omitted
throughout this paper. The insertion of an element in
a subset works as follows: the element is first inserted
into the subset’s own set, and then is recursively in-
MODELSWARD 2018 - 6th International Conference on Model-Driven Engineering and Software Development
466