VC6 vs VC7
От: Pavel Dvorkin Россия  
Дата: 20.09.05 11:10
Оценка:
Уважаемые господа!

Не может ли кто-нибудь объяснить, почему этот код нормально линкуется в VC6, а в VC7.1 дает unresolved external на функцию operator<<

Причем если закомментировать friend, то все линкуется нормально, но тогда, естественно, не будет доступа к полям L1, если такие добавить private.

#include <iostream>
using namespace std;
template <class T>
class L1
{
public:
friend ostream& operator << (ostream& out,L1 &A);
};
template<class T>
ostream& operator << (ostream& out,L1<T> &A)
{
return out;
}
void main()
{
L1<int> l;
cout << l;
}
With best regards
Pavel Dvorkin
Re: VC6 vs VC7
От: Lorenzo_LAMAS  
Дата: 20.09.05 11:14
Оценка:
Это потому, что другом ты объявил обычную функцию. Ее объявление найдено в классе и такая функция предпочтительнее шаблона и потому компилятор выбрал ее при разрешении перегрузки и тут-то понадобилось отсутствующее объявление

ПС А в 6ом вижуале с шаблонами-друзьями все плохо
Of course, the code must be complete enough to compile and link.
Re: VC6 vs VC7
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 20.09.05 11:15
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:


PD>Уважаемые господа!


PD>Не может ли кто-нибудь объяснить, почему этот код нормально линкуется в VC6, а в VC7.1 дает unresolved external на функцию operator<<


PD>Причем если закомментировать friend, то все линкуется нормально, но тогда, естественно, не будет доступа к полям L1, если такие добавить private.


PD>#include <iostream>

PD>using namespace std;
PD>template <class T>
PD>class L1
PD>{
PD>public:
PD> friend ostream& operator << <T>(ostream& out,L1 &A);
PD>};
PD>template<class T>
PD>ostream& operator << (ostream& out,L1<T> &A)
PD>{
PD> return out;
PD>}
PD>int main()
PD>{
PD> L1<int> l;
PD> cout << l;
PD>}
Re[2]: VC6 vs VC7
От: Lorenzo_LAMAS  
Дата: 20.09.05 11:24
Оценка: +1
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Это потому, что другом ты объявил обычную функцию. Ее объявление найдено в классе и такая функция предпочтительнее шаблона и потому компилятор выбрал ее при разрешении перегрузки и тут-то понадобилось отсутствующее определение


L_L>ПС А в 6ом вижуале с шаблонами-друзьями все плохо
Of course, the code must be complete enough to compile and link.
Исправленный вариант
От: Глеб Алексеев  
Дата: 20.09.05 11:27
Оценка: 13 (3) +1
#include <iostream>
using namespace std;

template <class T>
class L1;

template<class T>
ostream& operator << (ostream& out,const L1<T> &A);

template <class T>
class L1
{
  public:
  friend ostream& operator << <>(ostream& out,const L1 &A);
};

template<class T>
ostream& operator << (ostream& out,const L1<T> &A)
{
  return out;
}

void main()
{
  L1<int> l;
  cout << l;
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Исправленный вариант
От: Pavel Dvorkin Россия  
Дата: 20.09.05 12:02
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

ГА> friend ostream& operator << <>(ostream& out,const L1 &A);


Спасибо за ответ. Действительно, в 7-м Visual это компилируется. Но

1. Это не компилируется в 6-м. Как же все таки сделать в рамках того С++, что был до VC7 ?
2. Что за операция (или что такое) <> ? Никогда с ней не сталкивался. Это из стандарта C++ ? В MSDN тоже не нашел.
With best regards
Pavel Dvorkin
Re[2]: Исправленный вариант
От: Lorenzo_LAMAS  
Дата: 20.09.05 12:06
Оценка: 13 (2)
Хоть я и не Глеб

1. Чтобы работало с шестым, можно определять функцию друг прямо в классе (раньше так в динкумваре делали своп для вектора, например), правда, если планируешь куда-то такое переносить (на зверски стандартный компилятор), то нужно, чтоб либо функция находилась по типу аргументов АДЛем (в твоем случае это так), либо чтоб она была предварительно объявлена где-то вне класса.
2. Это не операция, это Глеб показал, что друг — специализация шаблона (тип будет выведен из параметров функции, потому скобки пустые)
Of course, the code must be complete enough to compile and link.
Re[3]: Исправленный вариант
От: Pavel Dvorkin Россия  
Дата: 20.09.05 12:16
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:


L_L>1. Чтобы работало с шестым, можно определять функцию друг прямо в классе (раньше так в динкумваре делали своп для вектора, например), правда, если планируешь куда-то такое переносить (на зверски стандартный компилятор), то нужно, чтоб либо функция находилась по типу аргументов АДЛем (в твоем случае это так), либо чтоб она была предварительно объявлена где-то вне класса.


Это понятно, спасибо. Работает в 7-м без этого <>.

L_L>2. Это не операция, это Глеб показал, что друг — специализация шаблона (тип будет выведен из параметров функции, потому скобки пустые)


А вот насчет этого, если можно, чуть подробнее. Когда такое в языке появилось ? Это все же из стандарта или нет ?
With best regards
Pavel Dvorkin
Re[4]: Исправленный вариант
От: Lorenzo_LAMAS  
Дата: 20.09.05 12:27
Оценка:
PD>Это понятно, спасибо. Работает в 7-м без этого <>.
Какой пример работает без <> ?

PD>А вот насчет этого, если можно, чуть подробнее. Когда такое в языке появилось ? Это все же из стандарта или нет ?


Да, из стандарта. Только конкретизируй вопрос, почему надо объявлять друга с <...> или почему могут быть пустые <> ?
Of course, the code must be complete enough to compile and link.
Re[5]: Исправленный вариант
От: Pavel Dvorkin Россия  
Дата: 20.09.05 12:31
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

PD>>Это понятно, спасибо. Работает в 7-м без этого <>.

L_L>Какой пример работает без <> ?

С описанием функции внутри класса.


template <class T>
class L1
{
public:
friend ostream& operator << (ostream& out,const L1 &A)
{
    return out;
}
};




L_L>Да, из стандарта. Только конкретизируй вопрос, почему надо объявлять друга с <...> или почему могут быть пустые <> ?


Опять не понял. Кому я должен конкретизировать вопрос — тебе, MSDN или стандарту ?
With best regards
Pavel Dvorkin
Re[6]: Исправленный вариант
От: Lorenzo_LAMAS  
Дата: 20.09.05 12:34
Оценка:
PD>
PD>template <class T>
PD>class L1
PD>{
PD>public:
PD>friend ostream& operator << (ostream& out,const L1 &A)
PD>{
PD>    return out;
PD>}
PD>};

PD>


OK

PD>Опять не понял. Кому я должен конкретизировать вопрос — тебе, MSDN или стандарту ?

Мне
Of course, the code must be complete enough to compile and link.
Re: VC6 vs VC7
От: Pavel Chikulaev Россия  
Дата: 20.09.05 12:48
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:


PD>Уважаемые господа!


PD>Не может ли кто-нибудь объяснить, почему этот код нормально линкуется в VC6, а в VC7.1 дает unresolved external на функцию operator<<


Не совсем про твой вопрос, но это тоже очень важно:

Про друзей-"специализации шаблонов" есть хорошая статья Саттера в CUJ и Exceptional C++ Style:
http://www.cuj.com/documents/s=8244/cujcexp2101sutter/
Re[7]: Исправленный вариант
От: Pavel Dvorkin Россия  
Дата: 20.09.05 12:50
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:


PD>>Опять не понял. Кому я должен конкретизировать вопрос — тебе, MSDN или стандарту ?

L_L>Мне

Спасибо, в обшем-то понятно и так.

L_L>специализация шаблона (тип будет выведен из параметров функции, потому скобки пустые)


Тем более, что вариант с внутренним определением мне больше нравится.
With best regards
Pavel Dvorkin
Re: Исправленный вариант
От: R0man Украина  
Дата: 21.09.05 14:49
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:


ГА>template <class T>
ГА>class L1
ГА>{
ГА>  public:
ГА>  friend ostream& operator << <>(ostream& out,const L1 &A);
ГА>};


Если можно, по-подробнее об этом операторе <>...
Re[2]: Исправленный вариант
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 21.09.05 15:08
Оценка:
Здравствуйте, R0man, Вы писали:

R>Если можно, по-подробнее об этом операторе <>...


Почему бы не читать ветку целиком для начала?

здесь
Автор: Pavel Dvorkin
Дата: 20.09.05
Re[2]: Исправленный вариант
От: Глеб Алексеев  
Дата: 21.09.05 15:19
Оценка: 4 (1)
Здравствуйте, R0man, Вы писали:

R>Если можно, по-подробнее об этом операторе <>...

В принципе, выше по ветке сэр Лоренцо высказался по теме.
Кратко:
template <class T>
class A {
    friend ostream& operator<<(ostream&, const A<T>&);    // объявляет обычную функцию другом
    template <class U>
    friend ostream& operator<<(ostream&, const A<U>&);    // объявляет шаблонную функцию другом для всех U,
                                                        // а не только для T
    friend ostream& operator<< <T>(ostream&, const A<T>&);// объявляет специализацию с аргументом T шаблонной функции
                                                        // другом - как раз то, что нужно
    friend ostream& operator<< <>(ostream&, const A<T>&);// то же самое, аргумент шаблона выводится из аргументов функции
};
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Исправленный вариант
От: R0man Украина  
Дата: 21.09.05 15:35
Оценка:
Здравствуйте, Alxndr, Вы писали:

A>Здравствуйте, R0man, Вы писали:


R>>Если можно, по-подробнее об этом операторе <>...


A>Почему бы не читать ветку целиком для начала?


A>здесь
Автор: Pavel Dvorkin
Дата: 20.09.05


Для начала ветку прочитал, для продолжения вопрос решил задать автору кода.
Re[3]: Исправленный вариант
От: R0man Украина  
Дата: 21.09.05 15:36
Оценка:
Здравствуйте, Глеб Алексеев, Вы писали:

Спасибо большое. Ветку я прочитал, но все равно остались некоторый непонятности. Теперь все осознал.
Re: VC6 vs VC7
От: Dobre  
Дата: 04.10.05 13:24
Оценка:
Ребята, я вот тут у себя в большом и древнем проекте который писали ещё наши проотцы нашел, похоже, решение этой — ну или очень похожей проблемы:
Заранее извиняюсь, если уже кто то до меня это написал. Но я не нашел, потому и хочу поделиться своим счастьем:

Итак в чем проблема: А проблема в том, что если мы хотим использовать template функцию как friend у какого-нибудь класса, то натыкаемся на проблеммы:

template <typename T>
void delete_object(T * ob)
{
    delete ob;
}

class MyTest
{
    ~MyTest() {}
    friend void delete_object(MyTest*);
};

int main(int argc, char* argv[])
{
    MyTest * pTest = new MyTest();
    delete_object(pTest);
    
    return 0;
}

Проблема данного кода в том, что он не линкуется в VC6.0:
error LNK2001: unresolved external symbol "void __cdecl delete_object(class MyTest *)" (?delete_object@@YAXPAVMyTest@@@Z)


Следующие изменения не спасают в VC6.0:
class MyTest
{
    ~MyTest() {}
    friend void delete_object<>(MyTest*);       
    или
    friend void delete_object<MyTest>(MyTest*);  
};


Compiling...
error C2143: syntax error : missing ';' before '<'


Так вот как справились с этой проблемой наши проотцы:
они выкинули определение шаблонной функции в отдельный хеадер файл и его включили его туда где он необходим.
то есть:


// MyTest.h

class MyTest
{
    ~MyTest() {}
    friend void delete_object(MyTest*);
};




// TemplateMethods.h

template <typename T>
void delete_object(T * ob)
{
    delete ob;
}



// Test.cpp
#include "stdafx.h"
#include "MyTest.h"
#include "TemplateMethods.h"

int main(int argc, char* argv[])
{
    MyClass * pMy = new MyClass();
    delete_object(pMy);
    return 0;
}



Откомпилялось и работает в VC6.0
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.