2016-12-28 14 views
0

My C++コンパイラはC++ 14です。私はすべての種類のエラーコードをカプセル化するカスタムクラスのオブジェクトを取り込む関数を持っています。このパラメータは参照渡しされます。カスタムクラスオブジェクトには、有効なエラー値&が空になることがあります。私はC++ 14ですてきな新しいものを見つけました。それはstd::experimental::optionalです。今私は実際にoptionalパラメータであるので、私は自分のパラメータにこれを使用しようとしています。続きリファレンスでパラメータとしてstd :: experimental :: optionalを使用する

はSTDと私の関数のシグネチャである::私が使用しようとしていますという実験::オプション:

MyFunction(some param, std::experimental::optional<MyCustomErrorClass> & error_code) { 

    //some logic 
    //sometimes error_code is populated & sometimes not populated 
} 

以下は、どのように私はMyFunctionを呼び出しています:

MyCustomErrorClass error_code_object; 
MyFunction(some_param, error_code_object); 

次のコンパイラエラーが表示されます。

error: non-const lvalue reference to type 'std::experimental::optional< MyCustomErrorClass>' cannot bind to a value of unrelated type 'MyCustomErrorClass' MyFunction(some_param, error_code_object); 

これを多く検索しました。 std::experimental::optionalまたはstd::optionalの使用例のほとんどは、それを関数の戻り値として示しています。

私のstd :: experimental :: optionalの使い方は何ですか?

+0

_Why_は、非const参照によって渡された 'error_code'ですか?純粋に入力パラメータの場合は、他のパラメータと同様にconst-refを渡します。 – ildjarn

+0

C++ 14は標準です。コンパイラを記述する際には、その名前、バージョン番号、プラットフォームを使用してください。 –

+0

@LightnessRacesinOrbit申し訳ありません。私のコードはclang、gcc、およびmicrosoft windowsでコンパイルされています。すべて3です。 –

答えて

2

これは約std::experimental::optionalではありません。一時的に左辺値参照にバインドしようとしていますが、これは不可能です。

この一時的なのは、MyCustomErrorClassからoptional<MyCustomErrorClass>への暗黙的な変換の結果です。

あなたの問題のための適切なMCVEは次のとおりです。intlong

void f(long&); 

int main() 
{ 
    int x = 42; 
    f(x); 
} 

// error: invalid initialization of non-const reference of type 'long int&' from an 
//   rvalue of type 'long int' 

暗黙的な変換は可能ですが、その結果、一時は左辺値参照にバインドすることはできません。

代わりにoptionalオブジェクトを事前に構築し、名前で渡します。

optional<MyCustomErrorClass> opt_error_code_object = MyCustomErrorClass{}; 
MyFunction(some_param, opt_error_code_object); 
+0

しかし、paramをオプションにすることで、コードをそのままコンパイルすることができます。通常の 'MyCustomErrorClass'オブジェクトを渡す代わりに、オプションでparamを&から削除します。 –

+0

@SegmentationFault:もちろん、もちろんです。型が最初に一致する場合、暗黙の変換は必要ありません。したがって、一時的ではなく実際のオブジェクトへの参照を渡します。上の 'f'を' long& 'の代わりに' int& 'をとるのと同じです。タイプが同じでない場合は、問題が発生します。 –

1

あなたの機能はオプションでMyCustomErrorClassではありません。これはオプションではありません。MyCustomErrorClassです。そして、あなたはそれを参照することで、それを突然変異させることができ、渡されたオブジェクトを突然変異させようとします。実際にはoptional<T>でないものに対しては、optional<T>の操作を実行することはできません。あなたが本当に、本当にしたいと思ったらあなたができると思うが、悪いことはそのようなことを行う人々に起こる)。

+0

ほとんどですが、それほどではありません。 –

2

ここではオプションで参照する必要はありません。

オプションのリファレンスは、オプションのリファレンスとは非常に異なるビーストです。 2番目はC++に投票されませんでした。なぜなら、それは混乱するセマンティクスを持っているからです。しかし、あなたが望むものに近いでしょう。

オプションは、 a コピーのデータをそれ自身の中に格納します。したがって、オプションの参照は、オブジェクトのコピーを含むコンテナへの参照です。

エラーオブジェクトを、エラータイプのオプションの参照を必要とする関数に渡すと、エラーオブジェクトが最初に一時オプションにコピーされます。次に、それを一時的に(左辺)参照にバインドしようとします。それは違法です。だからあなたのコードはコンパイルに失敗します。

一時的ではないオプションを作成するか、一時値を左辺値にキャストすることで "修正"すると、関数はコピーされた関数と互換性があるため、おそらくまだ得られません。元のエラーオブジェクト。

通常、参照によってオブジェクトを渡すときに、変更を伝える必要があります。しかし、彼らはオプションの中のコピーを越えて伝えません。

解決策は、ポインタMyCustomErrorClass*を取ることです。これはnullable(オプションのような)であり、コピーを格納しません。呼び出し元サイトに&を追加するだけで、渡す必要がない場合はnullptrを使用します。

関連する問題