2017-03-24 4 views
9
class A { 
    public: 
     int num; 
     A (int param) : num(param) {} 
     operator decltype(auto)(){ return num; } 
}; 

class B { 
    public: 
     int num; 
     A objA; 
     B (int param) : num(param), objA(param) {} 
     //operator A()  { return objA; }   // Works    // #1 
     //operator int()  { return objA; }   // Works    // #2 
     //operator char() { return objA; }   // Actually Not Needed // #3 
     //operator double() { return objA; }   // Actually Not Needed // #4 
     operator decltype(auto)(){ return objA; } // Does NOT Work  // #5 
}; 

int main(){ 

    A objA(1); 
    int x1 = int(objA); 
    char y1 = (char) objA; 
    double z1 =  objA; 

    B objB(2); 
    A objA2  = objB; 
    int  x2 = objB; 
    char  y2 = objB; 
    double z2 = objB; 

    return 0; 
} 

このコードはclangでもgccでもコンパイルされないため、正しくないと見なします。しかし、私が行#5をコメントアウトし、#1と#2の行のコメントを外すと、プログラムは両方のコンパイラで正しく動作します(行#3と#4は実際には必要ありません)。C++でdecltype(auto)を使用する変換関数14

私が知る限り、必要な変換シーケンスは両方のシナリオで定義されています。なぜ誰がこのプログラムが正しくないのか分かりますか?私は何が欠けていますか?

答えて

3

implicit conversion sequenceには、1つのユーザー定義変換のみを含めることができます。その後、コードはint x2 = objB;で動作しません。 BAに変換され、Aintに変換され、両方ともユーザー定義変換です。

あなたはBoperator int()を提供する場合Bが直接intに変換される可能性があるため、それが正常に動作します。 (そしてまたintは、標準的な変換によって変換することができたし、chardoubleで動作します。)

+0

、私はdidnの:私はあなたの信念は、実際にあなたがそうするようにテンプレートを必要とするときoperator decltype(auto)(){/*...*/}は、変換が必要とされているクラスを返すようにしようとすることだと思いますそのルールについて知りません。しかし、2番目のケースでは、Bがintに直接変換できると言うと、変換可能関数がAを返すため、2つのユーザー定義変換もあります(Bはintに直接変換できません)。 '演算子int(){戻り値objA; } '(これは最初のユーザ定義の変換です)、クラスAのオブジェクトを返します。これは、他のユーザ定義変換でintに変換する必要があります。' operator decltype(auto)(){return num; } '。それは正しいのではないですか?ご協力いただきありがとうございます。 –

+1

@JLはい、 'return objA;'に対して、 'objA'は' A'で定義された変換演算子によって 'int'に変換されます。しかしそれは別の変換シーケンスです。元の変換シーケンス(すなわち、 'B'から' int')は 'B :: operator int()'によって終了し、変換を行うことができます。それがどのように実装されるかは別の問題です。 – songyuanyao

+0

OK、あなたの言うことを理解していますが、他のケースでも同じことを言うことができませんでしたか?私は答えがノーだと思うので、それが間違っています。したがって、 'operator decltype(auto)(){return objA;}を使用します。 }}は、両方のユーザ定義コンバージョンが同じシーケンスにあることを意味しますが、他のケース( 'operator int(){return objA;}')には2つの異なる変換シーケンスがあります。私は完全に理解していない1つのケースでは、同じ変換シーケンスであり、他のケースでは2つの異なる変換シーケンスと見なされますが、正解のように聞こえる。もう一度あなたの助けをありがとう:) –

5

decltype(auto)あなたはを返すしているタイプの(参照やポインタを含む)正確な型を取得します。 class Aの場合、変換演算子はintを返し、class Bの場合はclass Aを返します。

class A { 
    public: 
     int num; 
     A (int param) : num(param) {} 

     template<class T> 
     operator T(){ return static_cast<T>(num); } 
}; 

class B { 
    public: 
     int num; 
     A objA; 
     B (int param) : num(param), objA(param) {} 

     template<class T> 
     operator T (){ return static_cast<T>(objA); } 
}; 
非常に面白そう

Live Demo

+0

あなたの提案をありがとう、その非常に役立つ。しかし、私の主な関心事は、変換関数のプロセスを理解すること、なぜこの場合には機能しないのかということです。 'class B'の変換関数が適用され、' class A'を返すとき、なぜ 'class A 'がintに変換できないのか分かりますか?必要な変換シーケンスが定義されています( 'operator decltype(auto)(){return num;}')。あるいは、クラスBの変換関数が最初に適用されなかったかもしれませんか?どうして?あなたの助けをもう一度ありがとう。 –

+1

@JLこれは、ユーザー定義の変換が連鎖できないためです。これは、[songyuanyaoの答え](http://stackoverflow.com/a/43003042/27678)です – AndyG

関連する問題