2014-05-12 2 views
3

Почему не компилируется следующий код?Определенные пользователем и стандартные преобразования

#include <iostream> 
using namespace std; 

struct CL1{}; 

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

void fnc(const CL1&) 
{ 
} 

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

Не работает ли две конверсии?

  1. определенного пользователь преобразование int в CL2
  2. стандартного преобразования производных к основанию (CL2 к const CL1&)

стандарт (2003) говорит:

пользователь мог определенная последовательность преобразования состоит из начальной стандартной последовательности преобразования, за которой следует пользовательское преобразование (12.3), за которым следует secon d стандартная последовательность преобразования.

Почему это не работает?

+1

Я не использую сам стандарт, но если это работает, компилятор должен будет проверить все допустимые (неявные) конструкторы всех подклассов класса. Это может создать некоторые интересные проблемы с кодом, который «магически» компилируется при добавлении, казалось бы, несвязанного заголовка (содержащего некоторый подкласс) или столкновений конструкторов разных классов. – user1781290

+1

Хммм ... Я не знаю, что говорит стандарт по этому вопросу, но при том, что вы могли бы иметь несколько корней из int в CL1, если это было разрешено (скажем, если у вас CL3, который идентичен CL2), я бы предположил, что это будет жаловаться где-то еще в стандарте. – IdeaHat

ответ

2

Нет стандартных преобразований, содержащих ссылки, поэтому правило здесь не имеет отношения. Вместо этого нам нужны правила для инициализации ссылок, приведенных в C++ 11 8.5.3. Это довольно сложно; соответствующий один здесь является завершающим пуля пункта 5 (для случая, когда инициализатор не ссылаться на совместимость с ссылочного типа):

временного типа cv1 T1 создается и инициализируется из выражения инициализатора используя правила для нереференсного копирования инициализации

Здесь cv1 T1 является const CL1. Невозможно создать временный T1 от int, и поэтому инициализация завершится неудачно. Компилятору не требуется искать все типы, полученные или ссылочные по ссылочному типу; он рассматривает только ссылочный тип. Вы должны указать, что вы хотите создать CL2:

func(CL2(5)); 

, который, будучи ссылки совместим с const CL1, может быть использован для определения ссылки.

ПРИМЕЧАНИЕ. Я цитирую C++ 11, поскольку это был стандарт в течение нескольких лет. Правила и номера разделов были, по сути, одинаковыми в C++ 03 (и действительно C++ 98).

Смежные вопросы