63 votes

Est-ce que toutes/la plupart des fonctions setter en C++11 devraient être écrites comme des modèles de fonctions acceptant des références universelles ?

Considérons une classe X con N variables membres, chacune d'une certaine copiable y mobile et N les fonctions setter correspondantes. En C++98, la définition de X ressemblerait probablement à quelque chose comme ça :

class X
{
public:
    void set_a(A const& a) { _a = a; }
    void set_b(B const& b) { _b = b; }
    ...
private:
    A _a;
    B _b;
    ...
};

Fonctions Setter de la classe X ci-dessus peut se lier à la fois à des arguments de type lvalue et rvalue. En fonction de l'argument réel, ce pourrait entraînent la création d'un poste temporaire et sera éventuellement aboutir à une affectation de copie ; pour cette raison, non copiable ne sont pas pris en charge par cette conception.

Avec C++11, nous disposons d'une sémantique de déplacement, d'un transfert parfait et de références universelles (selon la terminologie de Scott Meyers), qui permettent une utilisation plus efficace et généralisée des fonctions setter en les réécrivant de cette manière :

class X
{
public:
    template<typename T>
    void set_a(T&& a) { _a = std::forward<T>(a); }

    template<typename T>
    void set_b(T&& b) { _b = std::forward<T>(b); }
    ...
private:
    A _a;
    B _b;
    ...
};

Les références universelles peuvent se lier à const /non- const , volatile /non- volatile et à tout type convertible en général, en évitant la création de temporaires et en transmettant directement les valeurs à l'utilisateur. operator = . Non copiable , mobile sont désormais pris en charge. Les liaisons éventuellement indésirables peuvent être éliminées soit par le biais de static_assert ou par std::enable_if .

Ma question est donc la suivante : en tant que directive de conception En C++11, toutes (disons, la plupart) des fonctions setter devraient-elles être écrites comme des modèles de fonctions acceptant des références universelles ?

En dehors de la syntaxe plus lourde et de l'impossibilité d'utiliser des outils d'aide de type Intellisense lors de l'écriture de code dans ces fonctions setter, y a-t-il des inconvénients pertinents avec le principe hypothétique " écrire les fonctions setter comme des modèles de fonctions acceptant les références universelles chaque fois que possible " ?

37voto

Puppy Points 90818

Vous connaissez les classes A et B, vous savez donc si elles sont mobiles ou non et si cette conception est finalement nécessaire. Pour quelque chose comme std::string Si vous avez un problème de performance, c'est une perte de temps de modifier le code existant, sauf si vous savez que vous avez un problème de performance. Si vous avez affaire à auto_ptr alors il est temps de l'arracher et de l'utiliser. unique_ptr .

Il est généralement préférable maintenant de prendre des arguments par valeur si vous ne savez rien de plus précis, comme par exemple

void set_a(A a) { _a = std::move(a); }

Ceci permet l'utilisation de n'importe quel constructeur de A sans exiger autre chose que la mobilité et offre une interface relativement intuitive.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X