Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conversion Function with decltype(auto) in C++14

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;
}

This code does not compile neither with clang nor with gcc, so I assume it is not correct. However, if I comment line #5 and uncomment lines #1 and #2 the program works correctly in both compilers (lines #3 and #4 are not really required).

As far as I know, the necessary conversion sequences are defined in both scenarios. Does anyone know why this program is not correct? What am I missing?

like image 382
J L Avatar asked Mar 24 '17 15:03

J L


1 Answers

decltype(auto) will get the exact type (including references and pointers) of the type you're returning. For class A your conversion operator will return an int, and for class B you will get it to return a class A. I think your belief is that operator decltype(auto) (){/*...*/} will try to return the class for which the conversion is needed, when in fact you would need a template to do so:

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

like image 164
AndyG Avatar answered Oct 27 '22 00:10

AndyG