La différence entre les suppresseurs dans std::shared_ptr
y std::unique_ptr
c'est que shared_ptr
est effacé par type, alors qu'en unique_ptr
Le type de suppresseur fait partie du modèle.
Voici l'explication de Stephan T. Lavavej comment l'effacement de type mène à l'exigence de CopyConstructible en std::function
.
Quant à la raison de cette différence entre les types de pointeurs, elle a été abordée à plusieurs reprises sur SO, par ex. aquí .
Une citation de ce que S.T.L. a dit :
Un "gotcha" très surprenant, je dirais, est que la std::function
nécessite des objets de fonction CopyConstructible, ce qui est plutôt inhabituel dans la STL.
Habituellement, la STL est paresseuse dans le sens où elle n'a pas besoin de choses au départ : si j'ai quelque chose comme un std::list
de type T
, T
n'a pas besoin d'être moins-que-comparable ; seulement si vous appelez la fonction membre list<T>::sort
alors il faut que ce soit moins que comparable.
La règle de base du langage qui sous-tend ce système est que les définitions des fonctions membres d'un modèle de classe ne sont pas instanciées tant qu'elles ne sont pas réellement nécessaires et que les corps n'existent pas dans un certain sens tant que vous ne les appelez pas.
C'est généralement cool - cela signifie que vous ne payez que pour ce dont vous avez besoin, mais std::function
est spécial en raison de l'effacement des types, car lorsque vous construisez le fichier std::function
à partir d'un objet appelable F
il doit générer tout ce dont vous pourriez avoir besoin à partir de cet objet. F
parce qu'il va effacer son type. Il a besoin de toutes les opérations dont il pourrait avoir besoin, qu'elles soient utilisées ou non.
Ainsi, si vous construisez un std::function
à partir d'un objet appelable F
, F
est absolument nécessaire au moment de la compilation pour être CopyConstructible. Ceci est vrai même si F
sera déplacé dans le std::function
donc même si vous lui donnez une valeur r et même si vous ne copiez jamais std::function
n'importe où dans votre programme, F
est toujours tenu d'être CopyConstructible.
Vous obtiendrez une erreur du compilateur qui vous le dira - peut-être horrible, peut-être agréable - selon ce que vous obtiendrez.
Il ne peut tout simplement pas stocker des objets mobiles à fonction unique. Il s'agit d'une limitation de conception causée en partie par le fait que std::function
remonte à boost/TR1, avant les références à la valeur r, et dans un certain sens, elle ne pourra jamais être corrigée avec std::function
L'interface de l'entreprise est telle qu'elle est actuellement.
Des alternatives sont à l'étude, peut-être que nous pouvons avoir une "fonction mobile" différente, donc nous obtiendrons probablement une sorte de wrapper effacé par type qui peut stocker la fonction mobile seulement dans le futur, mais std::function
dans l'état actuel de c++17, cela n'est pas possible, soyez-en conscient.