'Class diagram for variable member with the type of `std::unqiue_ptr<T>`

class Foo{};

class Demo
{
public:
    std::unique_ptr<Foo> foo_ptr{new Foo()};;
};

What's the relationship between Foo and Demo? I think it is composition. Am I right? How to draw such the relationship between them?

For the occasion that the variable member is not the type of std::unique and alike, at the association's end which tell that the class at the opposite has an attribute named after the role,e.g: enter image description here.

Then for the type of std::unique<T>, how to add the attribute?



Solution 1:[1]

Indeed, the relation between Demo and Foo that is implemented using std::unique_ptr is a kind of composition:

  • The unique_ptr ensures exclusive ownership of a Foo object
  • The unique_ptr ensures control of Foo‘s lifecycle, i.e. as you pointed out destruction of Demo implies destruction of owned Foo.
  • The fact that a unique_ptr can be moved is not an obstacle to the composition. On contrary, such transfers are explicitly allowed in UML.

It seems preferable to state a 0..1 multiplicity on the side of Demo, since your code does not require that all Foo instances necessarily belong to Demo:

enter image description here

I would not use the dot notation here, as I think it could mislead to think that Demo has a Foo member whereas Demo has only a unique_ptr that implements the composition of Foo. You could however use an open arrow on Foo side to document that the association is navigable in that diraction (via the pointer). Although there is no other semantic in UML behind this arrow, it could elegantly and informally suggest a pointer pointing to a target.

Solution 2:[2]

I can (right now) not give an answer to the notion of generics, but I can try to clarify a few things.

Your class code shows a public attribute foo_ptr which is initalized with an instance of a generic class being Foo. This is a simple attribute and you could denote that like

enter image description here (generics aside!)

There is no need to make that foo_ptr a composite aggregation. The latter is about object lifetime. And that should be derived from business requirements rather than from some implementation.

Composite aggregation means that the class instance is obliged to destroy the composite whenever it is terminated. So clearly some runtime implementation detail. If, and only if, that is the case then you add a filled diamond next to Demo. Else you go with a simple association.

As I learned the chosen language construct ensures that explicitely. However, if you go back to abstraction you need to document the cause for composite aggregation (which can not be found in the presented code). Just adding the diamond is only half of the truth. There must be some requirement/constraint that led to this construct.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2