Почему компилятор Visual Studio доволен
void fn(int *&i)
{
;
}
а также
void fn(IUnknown *const &p)
{
;
}
но нет
void fn(IUnkown *&p)
{
;
}
где звонит это выглядит
IDXGIFactory *df = nullptr;
// init df
fn(df);
ошибка компилятора
3 IntelliSense: ссылка типа «IUnknown *&«(не соответствует const) не может быть инициализирован значением типа« IDXGIFactory * »c: \ Users \ Carl \ Documents \ Visual Studio 2013 \ Projects \ Project1 \ Project5 \ main.cpp 29 10 Project5
Самое близкое, что я нашел в исследованиях, это то, что компилятор будет выполнять только одно преобразование типов за раз, но это не может быть правильным, потому что тогда Const & версия должна прерваться от выполнения преобразования типа и const; Однако это & версия, которая на самом деле не будет компилироваться.
Неконстантная ссылка lvalue (например, IUnknown*&
) может привязываться только к именующий; он не может связываться с Rvalue. Ссылочная lvalue-ссылка (например, IUnknown* const&
) Можно привязать к Rvalue.
Проще рассмотреть более простой случай, в котором не используются указатели или вызовы функций:
int i = 0;
double x = i; // (1) Well-formed
double const& y = i; // (2) Well-formed
double& z = i; // (3) Ill-formed
Вот, i
является объектом типа int
, когда i
используется в выражении, это именующий.
В (1), мы инициализируем объект x
(типа double
) от i
(типа int
). Тип не совпадает, но это нормально, потому что есть неявное преобразование из int
в double
, «Результатом» этого преобразования является Rvalue выражение(*) типа double
, который используется для инициализации x
,
В (2), мы инициализируем константную ссылку y
(типа double const&
) от i
, Опять же, типы не совпадают, поэтому неявное преобразование используется для преобразования int
в double
, «Результатом» этого преобразования является Rvalue. Как отмечалось вначале, ссылка, соответствующая const, может связываться с Rvalue, так y
привязан к «результату» конвертации.
В (3), мы пытаемся инициализировать неконстантную ссылку z
(типа double&
) от i
, Типы не совпадают, поэтому потребуется преобразование. Преобразование не может использоваться здесь, потому что «результат» преобразования является Rvalue, и, как было отмечено в начале, неконстантная ссылка не может связываться с Rvalue.
В C ++ есть специальные правила, позволяющие ссылкам const lvalue связываться с Rvalue выражения. Вы можете узнать, почему из других вопросов здесь, на StackOverflow, как «Почему неконстантная ссылка не может привязываться к временному объекту?»
Ваш случай точно такой же, как этот: тип вашего аргумента (IDXGIFactory*
) не совпадает с типом параметра (IUnknown*
или ссылка на него), поэтому для преобразования аргумента в тип параметра требуется неявное преобразование (в данном случае это преобразование из указатель на производный класс в указатель на базовый класс). «Результатом» этого преобразования является, однако, выражение rvalue, поэтому оно не может связываться с неконстантной ссылкой. IUnknown*&
,
(*)Это действительно prvalue; Я использовал таксономию выражения C ++ 98 в этом ответе для простоты. Увидеть этот вопрос для получения информации о категориях значений C ++ 11.
Других решений пока нет …