8

次の変換演算子が与えられた場合

struct A
{
    template<typename T> explicit operator T&&       () &&;
    template<typename T> explicit operator T&        () &;
    template<typename T> explicit operator const T&  () const&;
};

struct B {};

次の変換はすべて有効であると予想されますが、コンパイルエラーが発生するものもあります( live example ):

A a;

A&&      ar = std::move(a);
A&       al = a;
const A& ac = a;

B&&      bm(std::move(a));  // 1. OK
B&&      bt(A{});           // 2. OK
B&&      br(ar);            // 3. error: no viable conversion from A to B
B&       bl(al);            // 4. OK
const B& bz(al);            // 5. OK
const B& bc(ac);            // 6. OK

B        cm(std::move(a));  // 7. error: call to constructor of B ambiguous
B        ct(A{});           // 8. error: call to constructor of B ambiguous
B        cr(ar);            // 9. OK

特に、1 は 3 と同じように見え、2 とほとんど同じように見えますが (7 から 9、8 についても同様)、動作が異なります。

説明または回避策はありますか?

私の動機は、さらに別の 'any'です。最終的には、 ,explicitのような型特性の問題を回避するためにすべての変換演算子を作成する必要がありましたが、新しい問題にぶつかりました。std::is_constructiblestd::is_convertible

EDIT申し訳ありませんが、私の間違いである 3 と 9 は無視してください (Kerrek SB に感謝します)。しかし、7 と 8 は問題として残ります。あとexplicit、やっぱり関係ないようです、すみません。

EDIT 2ちょうどそれに気づいた

B        cm = std::move(a);
B        ct = A{};

変換演算子が でない場合は有効ですexplicit。そこで、explicit最初はサンプルでコピー初期化を使用していましたが、切り替えたときにexplicit直接初期化を使用する必要がありました。その後、この問題が発生しました (ケース 7 および 8)。

4

1 に答える 1