0

Given the following code in gcc-4.8.1

struct Base
{
};

struct Derive : private Base
{
};

void fn(Base, int);

struct Conv
{
    operator Base() const;
    operator Derive();
};

int main()
{
    Conv c;
    fn(c, 0);
    return 0;
}

When I gave above code, I got an error.I think compiler will select Conv::operator Base() but actually the compiler selected Conv::operator Derive()

But when I gave the following code, the compiler selected Conv::operator Base()

struct Base
{
};

struct Derive// : private Base
{
};

void fn(Base, int);

struct Conv
{
    operator Base() const;
    operator Derive();
};

int main()
{
    Conv c;
    fn(c, 0);
    return 0;
}
miskcoo
  • 185
  • 1
  • 6
  • Why do you think the compiler should select `Base` in that case (c is not `const`)? This is pretty much the `is_base_of` trick – nikolas Aug 28 '13 at 13:48
  • 1
    In fact, here's a detailed explanation: http://stackoverflow.com/a/2913870/1056003 – nikolas Aug 28 '13 at 13:50

2 Answers2

4

Your c object is non-const, so in the first case the Derive overload is an exact const-correct match that can still implicitly convert to Base. In the second example Derive can't convert to Base so the direct Base conversion has to be selected.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • But `Base` is private, `Derive` seems not to convert to `Base`. – miskcoo Aug 28 '13 at 13:56
  • 1
    @user2482012: access specifiers are not checked at this time. Only after the conversion sequence has been selected the access specifiers come into play. I added the specific quote (13.3.3.1/2) in an answer. – David Rodríguez - dribeas Aug 28 '13 at 13:59
2

The key is that access specifiers are not checked until the conversion sequence is selected, so the code feels like:

struct base {};
struct derived : base {};
struct conv { 
   operator base() const;
   operator derived();
};
void fn(base);
int main() {
   conv c;
   fn(c);
}

At this point there are different valid conversion sequences:

  • adding const qualification, then user conversion to base
  • user conversion to derived, derived to base conversion

The second conversion is a better conversion sequence and it is selected.

This is treated in the standard in 13.3.3.1/2:

Implicit conversion sequences are concerned only with the type, cv-qualification, and value category of the argument and how these are converted to match the corresponding properties of the parameter. Other properties, such as the lifetime, storage class, alignment, or accessibility of the argument and whether or not the argument is a bit-field are ignored. So, although an implicit conversion sequence can be defined for a given argument-parameter pair, the conversion from the argument to the parameter might still be ill-formed in the final analysis.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489