Xavier Lamorlette

C++ : idiomes

Copy and Swap

Implémentation de l'assignation par copie (copy assignment) par un passage de paramètre par valeur, qui appelle le constructeur par copie (copy constructor), puis par l'appel à une méthode swap(), qui échange les zones mémoires, sur ce paramètre.

Cette méthode swap() peut être utilisée pour le constructeur par mouvement (move constructor).

class A {
    A() {
      …
    }
    A(const A &) {
      …
    }
    A & operator=(A other) {
      swap(other);
      return * this;
    }
    A(A && other):
        A() {
      swap(other);
    }
    void swap(A & other) {
      …
    }
};

“« En masse » delegation”

class Proxy {
public:
    Proxy():
            implementation(new Real_object()) {
    }
    Real_object * operator->() {
        return implementation;
    }
private:
    Real_object * implementation;
};

Mixin

Une classe mixin fournit des méthodes à d'autre classes sans en être parente.
En C++ : classe template qui hérite de la classe paramètre template.

Le mixin est aussi appelé “Curiously Recurring Template Pattern”, “F-bound polymorphism”, ou “upside-down inheritance”.

Cela permet notamment d'implémenter :

PImpl

Cas particulier du design pattern Bridge.
“Pointer to implementation”, “compilation firewall”: cache les détails d'implémentation d'une classe dans une sous-classe dédiée que l'on accède via un “opaque pointer”.

Choix de conception : si on ne met dans la classe d'implémentation que les membres et méthodes privés, en laissant ceux publics dans la classe publique, on peut avoir des problèmes pour appeler des méthodes publiques depuis la classe d'implémentation. Par exemple, il faut rajouter dans la classe d'implémentation un pointeur vers la classe publique.

// A.hpp
class A {
public:
    A();
    ~A();

private:
    class Impl;
    std::unique_ptr<Impl> impl;
};

// A.cpp
class A::Impl {
…
};

A::A():
    impl(std::make_unique<Impl>()) {
}

A::~A() = default;

RAII

RAII: Resource Acquisition Is Initialisation: utilisation du destructeur, dont l'appel est garanti même en cas d'exception, pour libérer une ressource à la fin de sa portée de l'instance. La ressource est un invariant de classe lié à son existence.

Note : lorsqu'il y a plusieurs ressources à gérer, les variables locales sont détruites dans l'ordre inverse de leur construction.

Ceci est utilisé par les std::shared_ptr et les std::unique_ptr.

Son utilisation est fortement recommandée pour le contrôle des mutex, des allocations dynamiques de mémoire, des fichiers et des sockets.

Template Adapter

Classe template utilisée comme paramètre template.

Exemple :

template<typename T,
    template<typename> class Container_type = std::list>
class Stack {
public:
    void push(const T & element) {
        container.push_front(element);
    }

private:
    Container_type<T> container;
};

La dernière mise à jour de cette page date de février 2019.

Le contenu de ce site est, en tant qu'œuvre originale de l'esprit, protégé par le droit d'auteur.
Pour tout commentaire, vous pouvez m'écrire à xavier.lamorlette@gmail.com.