web-dev-qa-db-fra.com

Passer un paramètre facultatif par référence en c ++

Je rencontre un problème avec le paramètre de fonction facultatif en C++

Ce que j'essaie de faire, c'est d'écrire une fonction avec un paramètre facultatif qui est passé par référence, de sorte que je puisse l'utiliser de deux manières (1) et (2), mais sur (2), peu m'importe ce qui est la valeur de mFoobar.

J'ai essayé un tel code:

void foo(double &bar, double &foobar = NULL)
{
   bar = 100;
   foobar = 150;
}

int main()
{
  double mBar(0),mFoobar(0);

  foo(mBar,mFoobar);              // (1)
  cout << mBar << mFoobar;

  mBar = 0;
  mFoobar = 0;

  foo(mBar);                     // (2)
  cout << mBar << mFoobar;

  return 0;
}

mais ça plante

void foo(double &bar, double &foobar = NULL)

avec message:

error: default argument for 'double& foobar' has type 'int'

Est-il possible de le résoudre sans surcharge de fonction?

31
Moomin

L'argument par défaut d'une référence (mutable) doit être une valeur l. Le mieux que je puisse penser, sans surcharge, est

static double _dummy_foobar;
void foo(double &bar, double &foobar = _dummy_foobar)
30
kennytm

N'utilisez pas de références pour les paramètres facultatifs. Il n'y a pas de concept de référence NULL: une référence est toujours un alias vers un objet particulier.

Regardez peut-être boost::optional ou std::experimental::optional . boost::optional est même spécialisé pour les types de référence!

void foo(double &bar, optional<double &> foobar = optional<double &>())
39
Potatoswatter

Pourquoi ne pouvez-vous pas utiliser la surcharge de fonctions? C'est sûrement la solution la plus simple à votre problème?

void foo(double &bar, double &foobar) 
{ 
   bar = 100; 
   foobar = 150; 
}

void foo(double &bar) 
{ 
   double foobar = 0.0;
   foo(bar, foobar);
}
32
In silico

Une autre façon de procéder consiste à utiliser des pointeurs au lieu de références. Cela fournit la sémantique souhaitée sans surcharge. (Personnellement, j'irais probablement avec une surcharge.)

void foo(double* bar, double* foobar = 0)
{
   if (bar) *bar = 100;
   if (foobar) *foobar = 150;
}

   // ...

   foo(&mBar, &mFoobar);

   // ...

   foo(&mBar);

   // ...
5
pkh

Voici une autre façon folle qui n'entraîne pas de fuites de mémoire, que vous ne devriez jamais utiliser dans la vie réelle, mais qui semble conforme aux normes à première vue et se compile avec Visual C++ 2008 et g ++ 3.4.4 sous Cygwin:

void foo(double &bar, double &foobar = (*((double*)0)))
{
   bar = 100;
   double* pfoobar = &foobar;
   if (pfoobar != 0)
       foobar = 150;
}

Pour réitérer: NE FAITES PAS CECI! IL Y A DE MEILLEURES OPTIONS! LA SURCHARGE PEUT ÊTRE VOTRE AMI! Mais oui, vous pouvez le faire si vous êtes stupide et prudent. :)

4
CasaDeRobison

Il est beaucoup plus facile d'utiliser un type de pointeur et de le définir sur NULL que de définir la valeur par défaut/facultative pour un paramètre de référence.

1
Zorayr

En termes de paradigme orienté objet: si la classe donnée a et "Default", ce défaut doit être déclaré en conséquence, et peut ensuite être utilisé comme un "paramètre par défaut" Ex:

class Pagination {
private:
    int currentPage;
public:

    //...
    Pagination() {
        currentPage = 1;
        //...
    }

    // your Default Pagination (Must be initialized before thread concurrency)
    static Pagination& Default() {
        static Pagination p; 
        return p;
    }
};

Sur votre méthode ...

     //...
     std::vector<User>
     findByFilter(User& audit, Pagination& p = Pagination::Default() ) {
     // ...

Modifié: Cette solution est tout à fait appropriée car dans ce cas, il s'agit d'une pagination "par défaut globale" et d'une valeur "de référence" unique. Vous aurez également le pouvoir de modifier les valeurs par défaut telles que les préférences de navigation/d'affichage, etc.

Edit2: orthographe et correction ...

0
wdavilaneto