ссылка в параметрах шаблона
От: include2h  
Дата: 21.12.12 18:18
Оценка: -1
Вероятно я чего-то туплю, но вот такой вроде бы нормальный код не компилируется, выдает ошибку
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;
}


Почему? Я же хочу ссылку на указатель, а не ссылку на объект!
Re: ссылка в параметрах шаблона
От: breee breee  
Дата: 21.12.12 19:29
Оценка: 4 (1)
Здравствуйте, include2h, Вы писали:

I>Почему? Я же хочу ссылку на указатель, а не ссылку на объект!


Представьте, что вам удалось заставить это компилироваться. Тогда при преобразовании Derived* к Base* будет создан временный объект типа Base*. Ссылка на этот объект дает возможность модифицировать его (а не Derived* p), но в вызываемом коде обратиться к нему вы не сможете, т.к. он безымянен. Это действительно то, чего вы хотите?
Re[2]: ссылка в параметрах шаблона
От: breee breee  
Дата: 21.12.12 19:37
Оценка:
Вот минимальный код, который демонстрирует проблему:

void func1(long&) {}
void func2(const long&) {}

int main()
{
    int i = 1;

    func1(i); // error C2664
    func2(i); // ok
}


В C++ запрещено привязывать временный объект к ссылке на неконстанту. Хотя сообщение об ошибке в вашем случае какое-то странное. Куда-то делся указатель у Base*&. Возможно, баг MS VC++.
Re[3]: ссылка в параметрах шаблона
От: include2h  
Дата: 22.12.12 06:51
Оценка:
Здравствуйте, breee breee, Вы писали:

BB>В C++ запрещено привязывать временный объект к ссылке на неконстанту. Хотя сообщение об ошибке в вашем случае какое-то странное. Куда-то делся указатель у Base*&. Возможно, баг MS VC++.


Спасибо, я так и сделал с константами, теперь все работает. Правда, в типе есть одна особенность: константность можно указать не везде.
Вот так работает:
template<class T>
class MyTemplate
{
public:
    void Foo(T arg){}
};
//...
typedef MyTemplate<const BasePtr&> MyTemplateClass;


А так не компилируется:
template<class T>
class MyTemplate
{
public:
    void Foo(const T arg){}
};
//...
typedef MyTemplate<BasePtr&> MyTemplateClass;


Интересно почему?
Re[4]: ссылка в параметрах шаблона
От: breee breee  
Дата: 22.12.12 18:03
Оценка:
Здравствуйте, include2h, Вы писали:

I>Интересно почему?


В первом случае const относится к BasePtr (а не BasePtr&), что эквивалентно записи Base * const &.
Во втором случае const применяется к типу BasePtr&, т.е. к ссылке на указатель на Base. Обычно компилятор на константные ссылки выдает ошибку, но, возможно, есть какое-то правило про вывод типов шаблонов, что в этом случае const отбрасывается и в результате тип остается Base * &.

А все-таки, почему нельзя совсем выбросить ссылку, что избавит от всех проблем?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.