web-dev-qa-db-ja.com

C ++での参照によるオプションパラメータの受け渡し

C++のオプションの関数パラメーターに問題があります

私がやろうとしているのは、参照によって渡されるオプションのパラメータで関数を書くことで、2つの方法(1)と(2)でそれを使用できますが、(2)私は本当に何を気にしませんmFoobarの値。

私はそのようなコードを試しました:

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;
}

しかし、それはでクラッシュします

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

メッセージ付き:

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

関数をオーバーロードせずに解決することは可能ですか?

30
Moomin

(可変)参照のデフォルト引数はl値でなければなりません。私が考えることができる最高は、オーバーロードすることなく、

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

オプションのパラメーターに参照を使用しないでください。参照NULLの概念はありません。参照は常に特定のオブジェクトのエイリアスです。

多分 boost::optional または std::experimental::optionalboost::optionalは参照型にも特化しています!

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

なぜ関数のオーバーロードを使用できないのですか?確かにそれはあなたの問題に対する最も簡単な解決策ですか?

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

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

これを行う別の方法は、参照の代わりにポインターを使用することです。これにより、オーバーロードせずに必要なセマンティクスが提供されます。 (個人的には、おそらくオーバーロードに行きます。)

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

   // ...

   foo(&mBar, &mFoobar);

   // ...

   foo(&mBar);

   // ...
5
pkh

メモリリークを引き起こさない別のクレイジーな方法を次に示します。これは実際には使用すべきではありませんが、一見すると標準に準拠しているようで、Cygwinの下でVisual C++ 2008およびg ++ 3.4.4でコンパイルします。

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

繰り返しますが、これをしないでください!より良いオプションがあります!過負荷はあなたの友人になることができます!しかし、ええ、あなたが愚かで注意深いなら、あなたはそれをすることができます。 :)

4
CasaDeRobison

参照パラメーターのデフォルト/オプション値を設定するよりも、ポインター型を使用してNULLに設定する方がはるかに簡単です。

1
Zorayr

オブジェクト指向のパラダイムの観点から言えば、与えられたクラスが「デフォルト」を持っている場合、このデフォルトはそれに応じて宣言する必要があり、その後「デフォルトパラメータ」として使用できます例:

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;
    }
};

あなたの方法について...

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

編集:この場合、このソリューションは「グローバルなデフォルト」のページネーションと単一の「参照」値であるため、非常に適しています。また、ナビゲーション/ディスプレイの設定などのデフォルト値を変更することもできます。

Edit2:スペルと修正...

0
wdavilaneto