Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

код с шаблонами компилируется но не выполняется, нужен ваш анализ

26K
29 апреля 2007 года
spb
5 / / 29.04.2007
Такая загвоздка немогу организовать работу дружественной функции к шаблону класса. Код (приведен ниже) компилируется корректно, но не выполняется - ошибка линкеровщика: [Linker Error] Unresolved external 'func(MyClass<int>)' referenced from D:\....
Выполняю в Билдере неработает, в MS Visual работает. Как заставить именно этот код работать в Билдере(важно).

Код:
#pragma hdrstop
#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;
}
3
29 апреля 2007 года
Green
4.8K / / 20.01.2000
Не будет работать ни в BCB, ни в VC, ни в любом другом компиляторе С++, т.к. ты объявил две функции: одну шаблонную, а другую нет.

Для того, чтобы заработало, надо правильно написать первое объявление:
 
Код:
template <typename T>
class MyClass
{
    template<class S> friend void func(MyClass<T>);
};


Только friend-ы - это зло! Отказывайся от них!
26K
29 апреля 2007 года
spb
5 / / 29.04.2007
Вы рекомендовали изменить код согласно рекомендации:
 
Код:
template <typename T>
class MyClass
{
    template<class S> friend void func(MyClass<T>);
};

Поменял, его так:
Код:
#pragma hdrstop
#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]
3
29 апреля 2007 года
Green
4.8K / / 20.01.2000
Опечатался. Должно быть так:
 
Код:
template <typename T>
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 имя_программы
Тогда окно консоли не закроется.
26K
29 апреля 2007 года
spb
5 / / 29.04.2007
Цитата: Green
Попробуй с тем исправлением, которое я привел в этом посте. Если не заработает, значит, проблема в компиляторе, т.к. я проверил на VC++ и Comeau.

Так в том то и прикол, что в VC++ работало с тем кодом который был с самого начала поста, в Билдере неработает ни так как было, ни так как вот только что посоветовали. Неспорю что нужно иной раз сильно аргументировать выбор среды разработки в сторону Билдера, но тут как раз тот случай - лабораторные работы именно сдаются в среде Билдера. Неужели до меня никто с этим не сталкивался(дружественные функции в шаблоне класса) именно для Билдера?

3
29 апреля 2007 года
Green
4.8K / / 20.01.2000
Цитата: spb
Так в том то и прикол, что в VC++ работало с тем кодом который был с самого начала поста,


Он не мог работать. Точнее мог работать чисто случайно.
Почему, я уже объяснял. Нужно объяснить более детально?

Цитата: spb

Неужели до меня никто с этим не сталкивался(дружественные функции в шаблоне класса) именно для Билдера?


Компиляторы не полностью соответствуют стандарту языка С++.
Конструкция, которую я описал, вполне рабочая, проверено.
Борландовский компилятор (во всяком случае тот, который ты используешь), видимо, не поддерживает такие конструкции. Ты будешь удивлен какие ещё конструкции он не поддерживает. На форуме это уже не раз обсуждалось.
Дружественные шаблонные функции - это не эксклюзив, но особо часто не используются. Френды - это вообще плохо.
Я думаю, что в лоб решить твою задачу используя Борланд у тебя не получится. Вариантов несколько:
1) использовать др. компилятор,
2) не использовать friend,
3) не использовать шаблонную функцию, а, например, шаблонный метод дружественного класса.

И так, вариант 2 (рекомендую этот вариант):

Код:
template <typename T>
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:
Код:
template <typename T>
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. Кстати, объекты эффективнее передавать по ссылке, а не позначению.
350
30 апреля 2007 года
cheburator
589 / / 01.06.2006
Цитата: Green

 
Код:
template <typename T>
class MyClass
{
    template<class S> friend void func(MyClass<[color=red]S[/color]>);
};


Так... Это, я так понимаю, дружественный шаблон функции... А если надо сделать дружественным конкретную реализацию этой функции с таким же параметром T? Неужели запись

 
Код:
template <typename T>
class MyClass
{
    friend void func(MyClass<T>);
};

Не проканает? Реально, VC++ 8.0 вроде хорошо отвечает стандарту, и там все работает...
350
30 апреля 2007 года
cheburator
589 / / 01.06.2006
Цитата: spb
Код:
template <typename T>
class MyClass
{
friend void func(MyClass<T>);
};

template <class S>
void func(MyClass<S> _in)
{
};
}


А так не пробовал:

 
Код:
friend void func[color=red]<T>[/color](MyClass<T>);

А еще лучше, вообще забей на этот борланд...
3
30 апреля 2007 года
Green
4.8K / / 20.01.2000
Цитата: cheburator
Так... Это, я так понимаю, дружественный шаблон функции... А если надо сделать дружественным конкретную реализацию этой функции с таким же параметром T? Неужели запись
 
Код:
template <typename T>
class MyClass
{
    friend void func(MyClass<T>);
};

Не проканает? Реально, VC++ 8.0 вроде хорошо отвечает стандарту, и там все работает...


В этом случае нужно будет определять конкретную функцию, т.е. вместо

 
Код:
template <class S>
void func(MyClass<S> _in)
{
    cout<<_in.data<<'\n';
}

нужно будет писать
 
Код:
void func(MyClass<int> _in)
{
    cout<<_in.data<<'\n';
}


Цитата: cheburator
А так не пробовал:
 
Код:
friend void func[color=red]<T>[/color](MyClass<T>);


А это, вообще, нелепость какая-то.

26K
02 мая 2007 года
spb
5 / / 29.04.2007
Друзья, и участники обсуждения, рад сообщить что решение найдено: нужно было сначала определить дружественную функцию (или хотябы прописать ее прототип), а потом в заданни этой функции как дружественной в шаблоне класса расширить область видимости до глобльной:
Код:
template <class T> class MyClass;
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;
}
;)

Решение подсказали тут.
Всего Вам доброго!
3
02 мая 2007 года
Green
4.8K / / 20.01.2000
В данном случае это работает, но можно наступить на большущие грабли.
Дело в том, что
template <class T> void func(MyClass<T>);
и
void ::func(MyClass<T> _in);
это объявление не одной и той же функции. Первая шаблонная, а вторая - нет.

Грабли могут вылезти при частной специализации шаблонной функции:
Код:
template <class T> class MyClass;
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);

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог