Question

Why doesn't the following code compile?

#include <iostream>
using namespace std;

struct CL1{};

struct CL2:CL1
{
    CL2(int){cout<<"int";}
};

void fnc(const CL1&)
{
}

int main()
{
    fnc(5);
    return 0;
}

Isn't two conversions working?

  1. user-defined conversion int to CL2
  2. standard conversion derived-to-base (CL2 to const CL1&)

The standard (2003) says:

A user-defined conversion sequence consists of an initial standard conversion sequence followed by a user-defined conversion (12.3) followed by a second standard conversion sequence.

Why does this not work?

Était-ce utile?

La solution

There are no standard conversions involving references, so that rule isn't relevant here. Instead, we need the rules for initialising references, given in C++11 8.5.3. These are quite complicated; the relevant one here is the final bullet of clause 5 (for the case where the initialiser isn't reference-compatible with the reference type):

a temporary of type cv1 T1 is created and initialized from the initializer expression using the rules for a non-reference copy-initialization

Here, cv1 T1 is const CL1. There is no way to create a temporary T1 from int, and so the initialisation fails. The compiler isn't required to search all types derived from, or convertible to, the reference type; it only considers the reference type itself. You will have to specify that you want to create a CL2:

func(CL2(5));

which, being reference-compatible with const CL1, can be used to initialise the reference.

NOTE: I'm quoting C++11 since that's been the standard for some years. The rules and section numbers were essentially the same in C++03 (and indeed C++98).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top