код с шаблонами компилируется но не выполняется, нужен ваш анализ
Выполняю в Билдере неработает, в MS Visual работает. Как заставить именно этот код работать в Билдере(важно).
#pragma argsused
#include <iostream.h>
#include <conio.h>
template <typename T>
class MyClass
{
private:
T data;
public:
MyClass(T _in): data(_in){};
friend void func(MyClass<T>);
};
template <class S>
void func(MyClass<S> _in)
{
cout<<_in.data<<'\n';
};
int main(int argc, char* argv[])
{
MyClass<int> clas(3);
func(clas);
getch();
return 0;
}
Для того, чтобы заработало, надо правильно написать первое объявление:
class MyClass
{
template<class S> friend void func(MyClass<T>);
};
Только friend-ы - это зло! Отказывайся от них!
class MyClass
{
template<class S> friend void func(MyClass<T>);
};
Поменял, его так:
#pragma argsused
#include <iostream.h>
#include <conio.h>
template <typename T>
class MyClass
{
private:
T data;
public:
MyClass(T _in): data(_in){};
template<class S> friend void func(MyClass<T>);
};
template <class S>
void func(MyClass<S> _in)
{
cout<<_in.data<<'\n';
};
int main(int argc, char* argv[])
{
MyClass<int> clas(3);
func(clas);
getch();
return 0;
}
Теперь не компилирует вовсе (ошибка в стороке объявления в класе дружественной класу функции), что именно я не так понял, подскажите? Как сделать так чтобы заработало? Я тут: [email]fi1114@ukr.net[/email]
class MyClass
{
template<class S> friend void func(MyClass<[color=red]S[/color]>);
};
Но ошибка у тебя должна была вылезти в др. месте или вообще не вылезти.
Попробуй с тем исправлением, которое я привел в этом посте. Если не заработает, значит, проблема в компиляторе, т.к. я проверил на VC++ и Comeau.
Убедись, что при объявлении дружественной функции у тебя слово friend следует ЗА словом template (т.е. как в приведенном примере кода), а не наоборот.
P.S. К сути проблемы это не относится, но есть несколько замечаний:
1. После определения функций и методов точка с запятой не нужна. Интересно, что Comeau (4.3.9) на это ругнулся error-ом.
2. Я бы рекомендовал использовать #include <iostream> вместо #include <iostream.h>, и соотв-но указать namespace std.
3. getch(); - захламляет программу. Я пользуюсь FAR-ом, поэтому консольный вывод не пропадает. Можно ещё вызывать программу так (например, написать командной строке параметров отладки):
cmd /K имя_программы
Тогда окно консоли не закроется.
Так в том то и прикол, что в VC++ работало с тем кодом который был с самого начала поста, в Билдере неработает ни так как было, ни так как вот только что посоветовали. Неспорю что нужно иной раз сильно аргументировать выбор среды разработки в сторону Билдера, но тут как раз тот случай - лабораторные работы именно сдаются в среде Билдера. Неужели до меня никто с этим не сталкивался(дружественные функции в шаблоне класса) именно для Билдера?
Он не мог работать. Точнее мог работать чисто случайно.
Почему, я уже объяснял. Нужно объяснить более детально?
Неужели до меня никто с этим не сталкивался(дружественные функции в шаблоне класса) именно для Билдера?
Компиляторы не полностью соответствуют стандарту языка С++.
Конструкция, которую я описал, вполне рабочая, проверено.
Борландовский компилятор (во всяком случае тот, который ты используешь), видимо, не поддерживает такие конструкции. Ты будешь удивлен какие ещё конструкции он не поддерживает. На форуме это уже не раз обсуждалось.
Дружественные шаблонные функции - это не эксклюзив, но особо часто не используются. Френды - это вообще плохо.
Я думаю, что в лоб решить твою задачу используя Борланд у тебя не получится. Вариантов несколько:
1) использовать др. компилятор,
2) не использовать friend,
3) не использовать шаблонную функцию, а, например, шаблонный метод дружественного класса.
И так, вариант 2 (рекомендую этот вариант):
class MyClass
{
public:
T& getData() {
return data;
}
};
template <class S>
static void func(MyClass<S>& _in)
{
std::cout << _in.getData() << std::endl;
}
int main(int argc, char* argv[])
{
MyClass<int> myClass(3);
func(myClass);
return 0;
}
Вариант 3:
class MyClass
{
friend class D;
};
class D
{
public:
template <class S>
static void func(MyClass<S>& _in)
{
std::cout <<_ in.data << std::endl;
}
};
int main()
{
MyClass<int> myClass(3);
D::func(myClass);
return 0;
}
Но этот трюк усложняет код.
P.S. Кстати, объекты эффективнее передавать по ссылке, а не позначению.
class MyClass
{
template<class S> friend void func(MyClass<[color=red]S[/color]>);
};
Так... Это, я так понимаю, дружественный шаблон функции... А если надо сделать дружественным конкретную реализацию этой функции с таким же параметром T? Неужели запись
class MyClass
{
friend void func(MyClass<T>);
};
Не проканает? Реально, VC++ 8.0 вроде хорошо отвечает стандарту, и там все работает...
class MyClass
{
friend void func(MyClass<T>);
};
template <class S>
void func(MyClass<S> _in)
{
};
}
А так не пробовал:
А еще лучше, вообще забей на этот борланд...
class MyClass
{
friend void func(MyClass<T>);
};
Не проканает? Реально, VC++ 8.0 вроде хорошо отвечает стандарту, и там все работает...
В этом случае нужно будет определять конкретную функцию, т.е. вместо
void func(MyClass<S> _in)
{
cout<<_in.data<<'\n';
}
нужно будет писать
{
cout<<_in.data<<'\n';
}
А это, вообще, нелепость какая-то.
template <class T> void func(MyClass<T>);
template <typename T> class MyClass
{
private:
T data;
public:
MyClass(T _in): data(_in){};
friend void ::func(MyClass<T> _in);
};
template <class T> void func(MyClass<T> _in)
{
cout<<_in.data<<'\n';
}
int main(int argc, char* argv[])
{
MyClass<int> clas(3);
func(clas);
getch();
return 0;
}
Решение подсказали тут.
Всего Вам доброго!
Дело в том, что
template <class T> void func(MyClass<T>);
и
void ::func(MyClass<T> _in);
это объявление не одной и той же функции. Первая шаблонная, а вторая - нет.
Грабли могут вылезти при частной специализации шаблонной функции:
template <class T> void func(MyClass<T>);
template <typename T>
class MyClass
{
private:
T data;
public:
MyClass(T _in): data(_in){};
template<class S> friend void func(MyClass<S> _in);
//friend void ::func(MyClass<T> _in);
};
template <class T>
void func(MyClass<T> _in)
{
cout << _in.data << endl;
}
template <>
void func(MyClass<int> _in)
{
cout << "ps " << _in.data << endl;
}
void func(MyClass<int> _in)
{
cout << "miss " << _in.data << endl;
}
А вообще, см. пункт "14.5.3 Friends" стандарта, где ясно сказано, что дружественная шаблонная функция шаблонного класса объявляется так:
template<class C> friend int func(C);