Title: An extension to the subtype relationship in C
1An extension to the subtype relationship in C
- István Zólyomi, Zoltán Porkoláb and Tamás Kozsik
Eötvös Loránd University, Budapest, Hungary
scamel gsd kto_at_elte.hu
2The structure of this presentation
- Motivation with examples
- LokiTypelist (short reminder)
- Creating the Family hierarchy
- Converting between families
- Inclusion polymorphism (FamilyPtr and FamilyRef)
- Practical experiences
- Summary
3Motivation
- Maximal separation of functionalities
- Collaboration based design
- Better maintenance of code
- Easier to create classes with required behavior
- Create and handle classes as a collection of
independent components
4Example 1
Vehicle
Emergency
Truck
Car
EmergencyVehicle
PoliceCar
FireEngine
5ios
virtual
virtual
ostream
istream
virtual
iostream
fstreambase
ifstream
ofstream
fstream
6Possible solutions
- Virtual inheritance
- Intrusive specified in base classes
- More concerns implies exponential number of
virtual bases - Traits
- No subtype relationship using hierarchies in
traits - AOP, MDSC, CF
- are for slightly different problems
- are extensions to standard C
- Families subtype relationship implemented with
metaprogramming - Non-intrusive solution based on the C standard
7Terminology
- Class implementation of a concern
- Orthogonal concerns in independent hierarchies
- Collaboration-based design combining concerns
- Collect concerns to gain required behavior
- Family instrument to express collaboration of
concerns - Implemented as a single class template
- Collects concern classes as a mixin using
multiple inheritance - OO languages support conversions to a single
concern (base) - do not support conversions between families
(collections of concerns)
8Example 2 (Harold Ossher)
OpEval
OpCheck
OpDisplay
Operator
PlusCheck
PlusEval
PlusDisplay
Plus
9LokiTypelist
- Introduced by Andrei Alexandrescu (and others)
- Handles meta-information (types) in compile time
like conventional containers do with data in
runtime
ltclass Head, class Tailgt struct Typelist
- Any number of types can be listed using recursion
typedef Typelistltchar, Typelistltshort, Typeli
stltint, NullTypegt gt gt Scalars
- The last element of every list is LokiNullType
by convention (like \0 for C-strings)
10LokiTypelist (cont.)
- We can make the previous class definition linear
with predefined macros with NullType included
typedef TYPELIST_3(char,short,int) TheSameList
- Typelist has many operations in Loki appending,
indexed access, removing duplicates, etc
typedef AppendltScalars, TYPELIST_1(long)gtResult
ExtendedList
11Source code of family construction
template ltclass Listgt struct Family template
ltclass Head, class Tailgt struct Familylt
TypelistltHead,Tailgt gt public Head, public
FamilyltTailgt // --- Type name shortcuts
typedef FamilyltTailgt Rest typedef Familylt
TypelistltHead,Tailgt gt MyType // --- Copy
constructor Family(const MyType mt)
Head(mt), Rest(mt) // ---
"Recursive" constructor Family(const Head
head, const Rest rest) Head(head), Rest(rest)
template ltclass Headgt struct Familylt
TypelistltHead,NullTypegt gt public Head //
--- All in one constructor Family(const Head
head) Head(head)
12FAMILY_3(OpDisplay, OpEval, OpCheck) op
13Conversions between families
- Initialize the head class for each recursion step
- Template constructors provide conversion steps
(the same for operator)
template ltclass Head, class Tailgt template ltclass
FromTypegt Familylt TypelistltHead,Tailgt gt
Family(const FromType f) Head(f),
FamilyltTailgt(f)
FAMILY_3(PlusEval,PlusDisplay, PlusCheck)
sum FAMILY_2(OpEval,OpCheck) calculate calculat
e sum
14Advantages
- Type safe based on builtin language conversions
- Efficient no temporal families or objects are
used, objects are initialized directly - General and transparent not restricted to
families only, any user object can be converted
without explicit conversion call.
struct Minus public MinusEval, public
MinusDisplay, public MinusCheck Minus
subtract calculate subtract
15Limitations
- No duplicates in typelists or compile error
- Keyword explicit is suppressed because of
explicit constructor calls during conversion - Compilation fails if there is no default or copy
constructor and assignment operator
16Smart pointers
- Problems
- Conversion copies objects by value (slicing)
- No dynamic binding
- Solution smart pointers
- Implementation and usage similar to those of
Family
FAMILY_3(PlusDisplay, PlusEval, PlusCheck)
sum FAMILYPTR_2(OpDisplay, OpEval)
opPtr(sum) // --- Function call with explicit
cast static_castltOpDisplaygt(opPtr)-gtshow() //
--- In longer form with implicit cast OpDisplay
displayPtr opPtr displayPtr-gtshow()
17FAMILYPTR_1(OpEval)
OpEval head
FAMILYPTR_2(OpDisplay,OpEval)
OpDisplay head
FAMILYPTR_2(OpDisplay, OpEval) opPtr
points to
head OpDisplay head OpEval
points to
PlusDisplay
PlusCheck
PlusEval
18FamilyRef
- Similar to FamilyPtr
- Store references instead of pointers
- Consequences
- A FamilyRef object must be initialized
- Initializes by reference but copies by value
during assignment
FAMILY_3(PlusDisplay, PlusEval, PlusCheck)
sum // --- Initializes by reference FAMILYREF_3(
OpDisplay, OpEval, OpCheck) exprRef(sum) // ---
Copies by value exprRef sum
19include ltiostreamgt include "family.h" struct
Shape virtual void f() stdcout ltlt
"Shape" struct Circle public Shape
void f() stdcout ltlt "Circle" struct
Colored struct Filled void
main() FAMILY_3(Circle, Colored, Filled)
extCircle FAMILY_3(Colored, Filled, Shape)
extShape(extCircle) FAMILY_2(Filled, Colored)
extensions(extCircle) extensions extShape
extCircle FAMILYPTR_3(Colored, Filled, Shape)
extShapePtr(extCircle) Shape shapePtr
extShapePtr shapePtr-gtf() //
--- Prints Circle FAMILYPTR_3(Filled,
Colored, Circle) extCirclePtr(extCircle) extSha
pePtr extCircle // --- Object -gt
Pointer extShapePtr extCirclePtr // ---
Der. Pointer -gt Base Pointer extShape
extShapePtr // --- Pointer -gt Object (by value)
20Experiences
21Summary
- Support for collaboration based design
- Implementation uses LokiTypelist
- Non-intrusive solution
- Easy to understand and manage
- No extension to C
- Bad experience with compilers vs standards
- Features
- Composition of concerns in a single class
(Family) - Conversion between related families
- Dynamic binding with smart pointers and references
22scamel_at_elte.hu gsd_at_elte.hu kto_at_elte.hu
- István Zólyomi
- Zoltán Porkoláb
- Tamás Kozsik
Eötvös Loránd University, Budapest, Hungary
Download source from http//gsd.web.elte.hu