At most how many user-defined conversion operator can be implicitly applied during an implicit type conversion?

221 Views Asked by At

According to the working draft N3337 (the most similar draft to the published ISOC++11 standard) the answer is at most one.

N3337:

At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

[ Example:

struct X {
    operator int();
};

struct Y {
    operator X();
};

Y a;
int b = a; // error
           // a.operator X().operator int() not tried

int c = X(a); // OK: a.operator X().operator int()

—end example ]

But according to the result of compiling main.cpp with gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 and running a.out with the quoted statements in Ubuntu 14.04.3 LTS, the answer is not at most one.

main.cpp:

#include <iostream>
    
struct As
{
    operator int(){ std::cout<<"operator As::int()"<<std::endl; return 1; }
};

struct Bs
{
    operator int(){ std::cout<<"operator Bs::int()"<<std::endl; return As(); }
};
    
int main()
{
     int i=Bs();
    
     return 0;
}

compiling and running from terminal:

$ g++ -std=c++11 main.cpp
$ ./a.out

the result (output):

operator Bs::int()
operator As::int()

Did I misunderstand something or is N3337 wrong or does gcc contains a bug?

2

There are 2 best solutions below

3
On BEST ANSWER

There are no double conversions getting executed here.

You have two individual conversions taking place, in two separate places.

One conversion is in B::operator int().

The second conversion is in your main().

Let's try to think through this logically:

Remove main() entirely from your translation unit. Do you see any double conversions?

No.

Now, let's create a header file containing the following bits, call it structures.H:

struct As
{
    operator int();
};

struct Bs
{
    operator int();
};

Now, create a structures.C file, containing the contents of each one of these operators:

#include <structures.H>

B::operator int(){ std::cout<<"operator As::int()"<<std::endl; return 1; }
A::operator int(){ std::cout<<"operator Bs::int()"<<std::endl; return As(); }

Ok, do you still see any double-conversions here? No.

Now, create your main.C:

#include <structures.H>

int main()
{
     int i=Bs();

     return 0;
}

Do you see any double conversions taking place here? No, even though what we have now, with the two translation units, the same exact code you started with.

0
On

int i=Bs(); invokes Bs::operator int() implicitly.

return As() invokes As::operator int() implicitly.

These are two separate expressions.