2017-08-23 9 views
20

オプションの次のコードを考える:異なる結果はstdにキャスト:: <T>

#include <iostream> 
#include <optional> 

struct foo 
{ 
    explicit operator std::optional<int>() { 
     return std::optional<int>(1); 
    } 
    explicit operator int() { 
     return 0; 
    } 
}; 

int main() 
{ 
    foo my_foo; 
    std::optional<int> my_opt(my_foo); 
    std::cout << "value: " << my_opt.value() << std::endl; 
} 

gcc 7.2.0 writesvalue: 1

MSVC2017(15.3)およびclang 4.0.0 however writevalue: 0

C++標準で正しいのはどれですか?

答えて

18

これはダイレクト初期化であるため、enumerate the constructorsを選択して、最適なものを選んでください。 std::optionalに関連するコンストラクタは、次のとおりです。

constexpr optional(const optional& other); // (2) 
constexpr optional(optional&& other) noexcept(/* see below */); // (3) 

template < class U = value_type > 
/* EXPLICIT */ constexpr optional(U&& value); // (8), with U = foo& 

は(intfoo&fooから構築可能である場合(8)のみオーバーロードの解決に参加して保持するすべては、std::in_place_tstd::optional<int>でもない)生存している両方が、(8)は完全一致であります(2)(3)にはユーザー定義の変換が必要なので、推奨する必要があります。 gccはここで間違っています。

しかし、実際にはgccは(3)を呼び出しません。 my_foooptional<int>に変換した結果から直接my_optを直接初期化するだけです。 GCC 7.2プリント3しかし1a1b、または2のなしでこのプログラム:

は、私はそれが許容ルートだとは思いません。私は81952を提出した。

+0

私はいつもオーバーロード解決が非テンプレートを優先していると考えました。なぜここで違うのですか? – Rakete1111

+6

@ Rakete1111ここでは違いはありません。オーバーロードの解像度は、非テンプレートを「常に」優先するわけではありません。同等の変換シーケンス順位を有する2つの候補が与えられると、タイブレイカーのうちの1つは非テンプレートを好む。しかし、ここでは同等の変換順序のランキングはありません。 – Barry

+0

@ Barry同じランクで2回のコンバージョンはありませんか? 1つは 'int'に、8つは' optional 'に、もう1つは(2)になりますか? – Rakete1111

関連する問題