2017-03-24 44 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只能包含一个用户定义的转换。那么代码将不能用于int x2 = objB;; B转换为AA转换为int都是用户定义的转换。

如果您提供B中的operator int(),它可以正常工作,因为B可以直接转换为int。 (而且还与chardouble,到int可以通过标准的转换而转换成)。

+0

这听起来很有趣,我没不知道这个规则。然而,在第二种情况下,你说B可以直接转换为int,就我所见,还有2个用户定义的转换(B不能直接转换为int,因为该转换函数返回A):当我提供'operator int(){return objA; }'(这是第一个用户定义的转换)它返回一个类A的对象,该类应该被转换为一个int,并且用另一个用户定义的转换操作符decltype(auto)(){return num; }'。这不正确吗?谢谢你的帮助。 –

+1

@JL是的,对于'return objA;',''由'A'中定义的转换运算符将'objA'转换为'int'。但请注意,这是另一个转换序列;原来的转换序列(即从'B'到'int')已经由B :: operator int()完成了,它指出它可以进行转换;它如何实现这是另一回事。 – songyuanyao

+0

好的,我明白你的意思,但是我不能说另一种情况是一样的吗?我想答案是否定的,这就是为什么它是错误的。所以使用'运算符decltype(auto)(){return objA; }'意味着两个用户定义的转换都是相同的序列,但在另一种情况下('operator int(){return objA;}')有两种不同的转换序列,这是否正确?我不完全理解为什么在一种情况下是相同的转换序列,而在另一种情况下,它被认为是两种不同的转换序列,但这听起来像是正确的答案。再次感谢您的帮助:) –

5

decltype(auto)将得到确切的类型(包括引用和指针)你返回类型的。对于class A,您的转换运算符将返回一个int,而对于class B,您将返回class A。我觉得你的信念是,operator decltype(auto)(){/*...*/}将尝试恢复需要为其转换的类的时候,其实你需要一个模板,可以这样做:

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

感谢您的建议,它非常有帮助。但是,我的主要兴趣是理解转换函数的过程,以及为什么它不适用于这种情况。当'B类'的转换函数应用并返回'A类'时,你知道为什么'A类'不能转换为int吗?所需的转换序列被定义('operator decltype(auto)(){return num;}')。或者'B类'的转换函数不适用于第一位?为什么?再次感谢你的帮助。 –

+1

@JL这是因为用户定义的转换不能链接。这是[songyuanyao的回答说](http://stackoverflow.com/a/43003042/27678) – AndyG