Я хочу написать функцию, которая изменяет данный указатель любого типа; таким образом, я объявил, что моя функция принимает void*&
, полагаясь на неявное преобразование с любого указателя на void*
. Однако следующий код отказывается компилировать, заявив, что не может преобразовать int*
в void*&
.
void f(void*& x)
{
x = 0;
}
int main() {
int* a = new int;
f(a);
delete a;
return 0;
}
Обратите внимание, что он отлично работает, если f объявлен как принимающий int*&
(но затем теряет свою общность), или если f объявлен как принимающий void*
(но тогда f может только модифицировать свой аргумент локально).
Таким образом, независимо от того, работает ли какое-либо триангулярное правило преобразования T*
в void*
действует правило " T
to T&
implicit conversion", но не оба одновременно? Почему это так? Что я здесь не так понял?
(Я знаю, что могу использовать функцию шаблона для f, это в основном из любопытства).
Это потому, что бит ссылки. Ссылка на указатель на один тип не совпадает с ссылкой на указатель другого типа.
Разумеется, это можно решить, используя шаблоны:
template<typename T>
void f(T*& x) { ... }
Если бы это сработало, вы бы создали временную void*
из T*
(поскольку преобразование здесь действительно означает "создать новый объект другого типа"), который вы тогда привязывали бы ссылку, которая не будет работать, поскольку он не const. Что будет работать:
void f(void* const & x)
{
x = 0;
}
Но это скорее всего не то, что вы намеревались, поскольку оно относится к временному, а не к int*
.