Вероятно я чего-то туплю, но вот такой вроде бы нормальный код не компилируется, выдает ошибку
error C2664: 'MyTemplate<T>::Foo' : cannot convert parameter 1 from 'Derived *' to 'Base &'
(MSVC 2008)
template<class T>
class MyTemplate
{
public:
void Foo(T arg) {};
};
class Base
{
public:
int x;
};
class Derived : public Base
{
public:
int y;
};
typedef Base* BasePtr;
typedef MyTemplate<BasePtr&> MyTemplateClass;
int main()
{
MyTemplateClass obj;
Derived *p = new Derived;
obj.Foo(p);
return 0;
}
Почему? Я же хочу ссылку на указатель, а не ссылку на объект!
Здравствуйте, include2h, Вы писали:
I>Почему? Я же хочу ссылку на указатель, а не ссылку на объект!
Представьте, что вам удалось заставить это компилироваться. Тогда при преобразовании Derived* к Base* будет создан временный объект типа Base*. Ссылка на этот объект дает возможность модифицировать его (а не Derived* p), но в вызываемом коде обратиться к нему вы не сможете, т.к. он безымянен. Это действительно то, чего вы хотите?
Вот минимальный код, который демонстрирует проблему:
void func1(long&) {}
void func2(const long&) {}
int main()
{
int i = 1;
func1(i); // error C2664
func2(i); // ok
}
В C++ запрещено привязывать временный объект к ссылке на неконстанту. Хотя сообщение об ошибке в вашем случае какое-то странное. Куда-то делся указатель у Base*&. Возможно, баг MS VC++.
Здравствуйте, breee breee, Вы писали:
BB>В C++ запрещено привязывать временный объект к ссылке на неконстанту. Хотя сообщение об ошибке в вашем случае какое-то странное. Куда-то делся указатель у Base*&. Возможно, баг MS VC++.
Спасибо, я так и сделал с константами, теперь все работает. Правда, в типе есть одна особенность: константность можно указать не везде.
Вот так работает:
Здравствуйте, include2h, Вы писали:
I>Интересно почему?
В первом случае const относится к BasePtr (а не BasePtr&), что эквивалентно записи Base * const &.
Во втором случае const применяется к типу BasePtr&, т.е. к ссылке на указатель на Base. Обычно компилятор на константные ссылки выдает ошибку, но, возможно, есть какое-то правило про вывод типов шаблонов, что в этом случае const отбрасывается и в результате тип остается Base * &.
А все-таки, почему нельзя совсем выбросить ссылку, что избавит от всех проблем?