Pourquoi le constructeur de copie est-il appelé dans un lambda lors du déplacement d'un `unique_ptr`?

Zoso

Pourquoi ce code ne parvient-il pas à se compiler?

#include <memory>
#include <utility>

int foo() {
    auto num = std::make_unique<int>(1);
    auto func = [s = std::move(num)] {
        auto u = std::move(s); <-- ERROR!
        return *u;
    };
    return func();
}

L'erreur est:

<source>:8:14: error: call to deleted constructor of 'std::unique_ptr<int, std::default_delete<int>>'
        auto u = std::move(s);
             ^   ~~~~~~~~~~~~
/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../include/c++/10.2.0/bits/unique_ptr.h:468:7: note: 'unique_ptr' has been explicitly marked deleted here
      unique_ptr(const unique_ptr&) = delete;

Je ne peux pas comprendre pourquoi le constructeur de copie est appelé, qui est évidemment supprimé pour une unique_ptrconception. Je peux comprendre quelle est l'erreur, mais pas pourquoi elle est là en premier lieu.

Voici ce que je pense qui se passe mais je ne suis pas sûr. Si je déballe ce lambda dans une sorte de structla operator()comme

template <typename T>
struct Lambda{
  :
  :
  operator() const{
    auto u = std::move(s); // <-- error
  }
  private:
  std::unique_ptr<T> s;
};

Je pense que cela échouerait à compiler car move(s)cela changerait la valeur de sce qui n'est pas autorisée dans une constfonction. Les compilations auraient donc dû échouer en invoquant l'immuabilité du lamda. Même le correctif à cette erreur consiste à changer le lambda en mutable. Mais un autre semble être de faire sun shared_ptr(qui, selon moi, aurait dû échouer car le lambda serait toujours immuable) et c'est là que je suis confus.

J'ai essayé cela sur les deux clanget gccavec des résultats similaires. Alors, s'il vous plaît, quelqu'un peut-il m'aider à combler le vide dans ma compréhension?

Caleth

C'est parce que vous essayez de déplacer un membre de données dans une constfonction membre.

Le type et la catégorie de std::move(s)est const unique_ptr&&. Il n'y a pas de surcharge unique_ptr(const unique_ptr&&), la seule qui soit viable l'est unique_ptr(const unique_ptr&).

Je pense que cela échouerait à compiler car move(s)cela changerait la valeur de sce qui n'est pas autorisée dans une constfonction.

Non, movec'est simplement un static_cast.

Cet article est collecté sur Internet, veuillez indiquer la source lors de la réimpression.

En cas d'infraction, veuillez [email protected] Supprimer.

modifier le
0

laisse moi dire quelques mots

0commentaires
connexionAprès avoir participé à la revue

Articles connexes

TOP liste

chaudétiquette

Archive