37 votes

boost make_shared prend une référence constante. Y a-t-il un moyen de contourner ce problème ?

J'utilise des pointeurs partagés boost dans mon programme, et j'ai une classe qui prend comme paramètre une référence à un autre objet. Le problème que je rencontre est que la fonction make_shared exige que tous les paramètres soient des références constantes, et j'obtiens des erreurs de compilation si le constructeur de ma classe ne permet pas de passer des paramètres de référence constants.

Quelqu'un connaît-il la raison de cette situation ? En outre, y a-t-il quelque chose que je puisse faire pour contourner ce problème ?

exemple de code de ce qui me pose problème :

class Object
{
  public:
    Object(int& i)
    {
      i = 2;
    }
};

int main(int argc, char *argv[])
{
  int i = 0;
  boost::shared_ptr<Object> obj = boost::make_shared<Object>(i);
  return 1;
}
Il en résulte une erreur de compilation qui se lit comme suit

make_shared.hpp:185 : error : no matching function for call to `Object::Object(const int&)' (erreur : aucune fonction correspondante pour l'appel à `Object::Object(const int&)') note : les candidats sont : Object::Object(const Object&) note : Object::Object(int&)

Si le paramètre du constructeur d'Objects est un const int, cela fonctionne. Je suis curieux de savoir pourquoi make_shared se comporte de cette façon.

0 votes

Pouvez-vous nous montrer un peu de code pour démontrer comment vous voulez utiliser make_shared() ?

42voto

Jitse Niesen Points 2142

http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/make_shared.html dit : "Si vous devez passer une référence non-const à un constructeur de T, vous pouvez le faire en enveloppant le paramètre dans un appel à boost::ref". D'autres textes sur cette page semblent soutenir la réponse de Rüdiger Hanke.

0 votes

Génial, merci, je ne voulais vraiment pas utiliser ma solution de contournement ci-dessous.

8voto

Rüdiger Hanke Points 4592

Je ne peux pas parler pour les auteurs de la fonction, mais ... vous devez faire un choix. Si la fonction utilise une référence non constante, alors vous ne pouvez pas passer des objets const aux constructeurs qui prennent des références const.

D'après mon expérience, les constructeurs prenant des références constantes sont beaucoup plus courants que les constructeurs prenant des références mutables.

Les constructeurs peuvent avoir n Vous ne pouvez donc pas fournir une seule surcharge, mais vous devez prendre en compte toute combinaison de const/non-const, ce qui entraîne une explosion exponentielle des surcharges dont vous auriez besoin si vous vouliez fournir des surcharges pour tous ces paramètres. C++0x et le forwarding parfait devraient apporter une solution à ce problème, je pense.

0 votes

Une explication parfaite. Merci.

5voto

Jeff Hardy Points 5310

Jusqu'à Références aux valeurs r (voir la section intitulée "le problème du transfert") arrivent en C++0x, le transfert parfait est pratiquement impossible. make_shared fait juste du mieux qu'il peut avec ce qui lui est donné.

0 votes

+1 Quelqu'un a effectivement posté une explication pour expliquer pourquoi il faut utiliser boost::ref(..) :)

0 votes

Le lien est rompu.

0 votes

@Hugo merci, corrigé, bien que je pense que chaque compilateur a ajouté des références rvalue dans la dernière décennie :)

1voto

Tobias Points 415

Vous devez définir un constructeur de copie.

class Object
{
  public:
    Object(const Object& original)
    {
        // Copy original to new object
        // The reason for the const is this should not change the original 
    };

    Object(int& i)
    {
      i = 2;
    }
};

0voto

Craig H Points 4224

Bien que je ne sache toujours pas pourquoi boost make_shared m'impose cette limitation, j'ai trouvé un moyen de la contourner. Si je passe une référence constante à un pointeur du paramètre, je peux ensuite modifier ce pointeur. Voici l'extrait de code :

class Object
{
  public:
    Object(int* const& i)
    {
      *i = 2;
    }
};

int main(int argc, char *argv[])
{
  int i = 0;
  boost::shared_ptr<Object> obj = boost::make_shared<Object>(&i);
  cout << i << "\n";
  return 1;
}

Celui-ci fonctionne comme un charme. Quelqu'un a-t-il une idée de la raison pour laquelle je dois sauter à travers ces cerceaux ? Il semble étrange que make_shared m'impose cette limitation, même si je reconnais que c'est probablement une mauvaise idée la plupart du temps.

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