web-dev-qa-db-ja.com

戻り時に暗黙的な変換は許可されていません

#include <optional>

bool f() {
  std::optional<int> opt;
  return opt;
}

コンパイルしません:'return': cannot convert from 'std::optional<int>' to 'bool'

参考資料を参考にして説明を探したのですが、大丈夫なので読んでみました。

暗黙的な変換は、あるタイプT1の式がそのタイプを受け入れないが他のタイプT2を受け入れるコンテキストで使用される場合は常に実行されます。特に:

  • t2をパラメーターとして宣言された関数を呼び出すときに、式が引数として使用される場合。
  • 式がT2を期待する演算子でオペランドとして使用される場合。
  • T2を返す関数のreturnステートメントを含む、タイプT2の新しいオブジェクトを初期化するとき
  • 式がswitchステートメントで使用されている場合(T2は整数型)。
  • 式がifステートメントまたはループで使用される場合(T2はブール値)。
21
darune

これは実際には暗黙的な変換ではなく、初期化のタイプに関するものです。

オプションには、明示的な変換関数があります。

explicit operator bool() const; 

N4849から[class.conv.fct]/p2

変換関数は明示的(9.2.2)である場合があります。その場合、直接初期化のためのユーザー定義の変換と見なされます。

上記は、これらのケースが変換関数を使用することを意味します:[dcl.init]/p16

発生する初期化(16.1)—括弧で囲まれた式リストまたは括弧付き初期リストである初期化子の場合(16.2)—新規初期化子(7.6.2.7)の場合(16.3)— static_cast式内( 7.6.1.8)、(16.4)—関数表記の型変換(7.6.1.3)、および(16.5)—条件の括弧付き初期リスト形式では、直接初期化と呼ばれます。

ただし、これらのケースでは変換関数を使用しません:[dcl.init]/p15

=括弧または等号初期化子または条件(8.5)の=形式で発生する初期化、および引数の受け渡し、関数の戻り、例外のスロー(14.2)、例外の処理(14.4)、およびメンバーの初期化(9.4.1)は、コピー初期化と呼ばれます。

問題の例は、コピーの初期化のケースに該当し、オプションの変換関数を使用していません。

1
Trixie