Шаблоны и их реализация
От: Yuri Dursin  
Дата: 05.04.02 09:38
Оценка:
Подскажите, можно ли при написании шаблонов реализацию методов помещать в *.cpp файл?
А то при небольшом изменении в реализации перекомпилируется весь проэкт, т. к. код приходится писать в *.h файле!
Durs
Re: Шаблоны и их реализация
От: Bell Россия  
Дата: 05.04.02 09:41
Оценка:
Здравствуйте Yuri Dursin, Вы писали:

YD>Подскажите, можно ли при написании шаблонов реализацию методов помещать в *.cpp файл?

YD>А то при небольшом изменении в реализации перекомпилируется весь проэкт, т. к. код приходится писать в *.h файле!

Нельзя
А чтобы проект весь не перекомпилить — смотри книгу Мейерса "Эффективное использование С++". Там этому вопросу целая глава посвящена.
Любите книгу — источник знаний (с) М.Горький
Re[2]: Шаблоны и их реализация
От: Sergey Россия  
Дата: 05.04.02 10:19
Оценка:
Здравствуйте Bell, Вы писали:

B>Здравствуйте Yuri Dursin, Вы писали:


YD>>Подскажите, можно ли при написании шаблонов реализацию методов помещать в *.cpp файл?

YD>>А то при небольшом изменении в реализации перекомпилируется весь проэкт, т. к. код приходится писать в *.h файле!

B>Нельзя


Ну почему ж нельзя — вполне можно, если все, кто использует шаблон, сидят в том же *.cpp файле. Да и декларировать его тогда удобнее в том же cpp файлы.

B>А чтобы проект весь не перекомпилить — смотри книгу Мейерса "Эффективное использование С++". Там этому вопросу целая глава посвящена.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re: Шаблоны и их реализация
От: Аноним  
Дата: 05.04.02 10:23
Оценка:
Здравствуйте Yuri Dursin, Вы писали:

YD>Подскажите, можно ли при написании шаблонов реализацию методов помещать в *.cpp файл?

YD>А то при небольшом изменении в реализации перекомпилируется весь проэкт, т. к. код приходится писать в *.h файле!

Шаблоны хорошее средство :maniac:
Если такой подход не слишком противоречит тому, что ты делаешь сейчас при помощи шаблонов, то можно сделать так: сделать класс, рассчитанный на любой тип данных и обернуть его шаблоном, вот слегка грубоватый пример:

class TCollect
{
public:
    TCollect(int aSizeIt);
    ~TCollect() { delete items; };
    int Count() const { return count; };
    UINT SizeBytes() const { return count*size_it; }
    UINT SizeElem()  const { return size_it; }
    char* At(int index) const { return items+(index*size_it); };
    BOOL Insert(int index, const void *item);
protected:
    char *items;
    int count;
    unsigned size_it;
};
template <class T> class TCollection : public TCollect
{
public:
    TCollection() : TCollect(sizeof(T)) {}
    BOOL Insert(const T &item, int i=-1) { return TCollect::Insert(i, &item); };
    T* At(int i) const { return (T*)TCollect::At(i); };
};


всего ;)
Re[3]: Шаблоны и их реализация
От: Bell Россия  
Дата: 05.04.02 10:30
Оценка:
Здравствуйте Sergey, Вы писали:

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


B>>Здравствуйте Yuri Dursin, Вы писали:


YD>>>Подскажите, можно ли при написании шаблонов реализацию методов помещать в *.cpp файл?

YD>>>А то при небольшом изменении в реализации перекомпилируется весь проэкт, т. к. код приходится писать в *.h файле!

B>>Нельзя


S> Ну почему ж нельзя — вполне можно, если все, кто использует шаблон, сидят в том же *.cpp файле. Да и декларировать его тогда удобнее в том же cpp файлы.


И насколько часто такие ситуации встречаются в реальной жизни?
В любом случае — это частность, а мы ведь не ищем легких путей!
Любите книгу — источник знаний (с) М.Горький
Re[2]: Шаблоны и их реализация
От: Yuri Dursin  
Дата: 05.04.02 10:33
Оценка:
Спасибо, понял — шансов мало!
Durs
Re[2]: Это не правильно!
От: Рек Россия  
Дата: 05.04.02 10:52
Оценка:
Здравствуйте Аноним, Вы писали:

А>
А>class TCollect
А>{
А>public:
А>    TCollect(int aSizeIt);
А>    ~TCollect() { delete items; };
А>    int Count() const { return count; };
А>    UINT SizeBytes() const { return count*size_it; }
А>    UINT SizeElem()  const { return size_it; }
А>    char* At(int index) const { return items+(index*size_it); };
А>    BOOL Insert(int index, const void *item);
А>protected:
А>    char *items;
А>    int count;
А>    unsigned size_it;
А>};
А>template <class T> class TCollection : public TCollect
А>{
А>public:
А>    TCollection() : TCollect(sizeof(T)) {}
А>    BOOL Insert(const T &item, int i=-1) { return TCollect::Insert(i, &item); };
А>    T* At(int i) const { return (T*)TCollect::At(i); };
А>};
А>


А>всего


Это совершенно неправильный пример использования шаблонов!

Шаблоны как раз позволяют (и предназначены для того чтобы) такое не писать!

И даже не потому, что плохо написано.
Такое просто не работает!
Re[3]: Это не правильно!
От: Bell Россия  
Дата: 05.04.02 11:06
Оценка:
Здравствуйте Рек, Вы писали:


Рек>Это совершенно неправильный пример использования шаблонов!


Рек>Шаблоны как раз позволяют (и предназначены для того чтобы) такое не писать!


Рек>И даже не потому, что плохо написано.

Рек>Такое просто не работает!

А вот Мейерс так не считает
У него есть подобный пример смеси класса-реализации и шаблонов (пример про стэк в книге "Эффективное использование")
Я не утверждаю, что именно так и надо делать, но в некоторых ситуациях такой подход имеет право на жизнь.
Любите книгу — источник знаний (с) М.Горький
Re[4]: Это не правильно!
От: Рек Россия  
Дата: 05.04.02 11:19
Оценка:
Здравствуйте Bell, Вы писали:

B>Здравствуйте Рек, Вы писали:



Рек>>Это совершенно неправильный пример использования шаблонов!


Рек>>Шаблоны как раз позволяют (и предназначены для того чтобы) такое не писать!


Рек>>И даже не потому, что плохо написано.

Рек>>Такое просто не работает!

B>А вот Мейерс так не считает

B>У него есть подобный пример смеси класса-реализации и шаблонов (пример про стэк в книге "Эффективное использование")
B>Я не утверждаю, что именно так и надо делать, но в некоторых ситуациях такой подход имеет право на жизнь.

Наговариваешь ты на Мейерса...

Ну давай хотябы посмотрим на строчку

~TCollect() { delete items; };

Что здесь будет удаляться? Если удаляется массив чаров, то хорошо бы поставить [].
А деструкторы объектов находящихся в контейнере отработают?
Как ты думаешь?

А уж на реализацию Insert как интересно было бы поглядеть!..
Re[5]: Это не правильно!
От: konst  
Дата: 05.04.02 11:33
Оценка:
почему не работает работает
не буду спорить на счёт чистоты стиля, конечно, нет никакой

вас интересовал инсёрт, вот, пожалуйста:

BOOL TCollect::Insert(int i, const void *item)
{
    if( i == -1 ) i = Count();
    if( count == limit )
    {
        int newLimit = min(limit+delta, MaxCount());
        if( newLimit == count ) return error(IDS_SE_MANYITEMS, g_hInstanceNCall), FALSE;
        char *ni;
        if( ISNULL(ni=new char[newLimit*size_it]) ) return FALSE;
        if( count != 0 ) memcpy(ni, items, count*size_it);
        delete items; items = ni; limit = newLimit;
    }
    if( i < count )    memmove(items+(i+1)*size_it, items+i*size_it, (count-i)*size_it);
    count++;
    if( item ) memcpy(items+i*size_it, item, size_it);
    else memset(items+i*size_it, 0, size_it);
    return TRUE;
}


его я не стал искажать — можно и ошибиться

и вы правы — вообще не для хранения объектов с деструктором и/или виртуальными функциями, а что делать идеальные решения не так часто встречаются
Re[6]: Это не правильно!
От: Рек Россия  
Дата: 05.04.02 12:23
Оценка:
Здравствуйте konst, Вы писали:

K>почему не работает работает

K>не буду спорить на счёт чистоты стиля, конечно, нет никакой

K>вас интересовал инсёрт, вот, пожалуйста:


K>
K>BOOL TCollect::Insert(int i, const void *item)
K>{
K>    if( i == -1 ) i = Count();
K>    if( count == limit )
K>    {
K>        int newLimit = min(limit+delta, MaxCount());
K>        if( newLimit == count ) return error(IDS_SE_MANYITEMS, g_hInstanceNCall), FALSE;
K>        char *ni;
K>        if( ISNULL(ni=new char[newLimit*size_it]) ) return FALSE;
K>        if( count != 0 ) memcpy(ni, items, count*size_it);
K>        delete items; items = ni; limit = newLimit;
K>    }
K>    if( i < count )    memmove(items+(i+1)*size_it, items+i*size_it, (count-i)*size_it);
K>    count++;
K>    if( item ) memcpy(items+i*size_it, item, size_it);
K>    else memset(items+i*size_it, 0, size_it);
K>    return TRUE;
K>}

K>


K>его я не стал искажать — можно и ошибиться


K>и вы правы — вообще не для хранения объектов с деструктором и/или виртуальными функциями, а что делать идеальные решения не так часто встречаются


Да. Наверное ты прав и такого типа контейнер сможет работать с некоторыми типами.
(только с типами, допускающими побитовое копирование — это простые типы (int, double, указатели), и структуры из них).

А для чего такое ограничение? Что ты получаешь взамен? Сверх эффективную memcpy ?
Но ведь типы, допускающие побитовое копирование, как правило малы по размерам,
и сомнительное преимущество memcpy тут никчему. Так что я не вижу никаких преимуществ этого метода.

Шаблоны тут используются всего лишь для "автоматизации приведения", для скрытия приведения.
А ведь шаблоны позволяют обойтись совсем без приведения. И позволяют работать с любыми типами.
Вот что главное!

Неужели Майерс?
Re[7]: Это не правильно!
От: konst  
Дата: 05.04.02 12:46
Оценка:
я когда то сам делал такую коллекцию для себя, почему именно так — не помню уже, но оно где-то потерялось; это то, что на работе я встретил, чем пользуюсь зато, почему так получилось, знаю — когда сделали коллекцию, ещё не было темплейтов и стандарта а всё переделывать, видимо, поленились да и сейчас неохота
Re[7]: Это не правильно!
От: konst  
Дата: 05.04.02 12:50
Оценка:
забыл вот ещё что: любой сложности объекты можно пихать туда, только без деструкторов и виртуальных методов (последнее тоже можно, но опасно, если вожможно в другой процесс передать)
Re[5]: Это не правильно!
От: Bell Россия  
Дата: 06.04.02 05:03
Оценка:
Здравствуйте Рек, Вы писали:

делать, но в некоторых ситуациях такой подход имеет право на жизнь.

Рек>Наговариваешь ты на Мейерса...


Рек>Ну давай хотябы посмотрим на строчку


Рек>~TCollect() { delete items; };


Рек>Что здесь будет удаляться? Если удаляется массив чаров, то хорошо бы поставить [].

Рек>А деструкторы объектов находящихся в контейнере отработают?
Рек>Как ты думаешь?

Рек>А уж на реализацию Insert как интересно было бы поглядеть!..


Сорри, несколько не так выразился — я имел в виду именно подход — есть класс, который обеспечивает некоторую функциональность, оперируя к примеру
void*
, и есть шаблон, который наследуется от этого класса (у Мейерса в примере — закрытое наследование). Вот этот шаблон и обеспечивает типизацию.
Я именно это имел ввиду. Т.е. с таким подходом можно и шаблон получить, и реализацию вынести в отдельную единицу компиляции.
А что касается конкретной реализации TCollect — народ уже высказался по этому поводу, я повторять не буду...
Любите книгу — источник знаний (с) М.Горький
Re[7]: Это не правильно!
От: Micker  
Дата: 06.04.02 07:05
Оценка:
Здравствуйте Рек, Вы писали:

Рек>Здравствуйте konst, Вы писали:


K>>почему не работает работает

K>>не буду спорить на счёт чистоты стиля, конечно, нет никакой

K>>вас интересовал инсёрт, вот, пожалуйста:


K>>
K>>BOOL TCollect::Insert(int i, const void *item)
K>>{
K>>    if( i == -1 ) i = Count();
K>>    if( count == limit )
K>>    {
K>>        int newLimit = min(limit+delta, MaxCount());
K>>        if( newLimit == count ) return error(IDS_SE_MANYITEMS, g_hInstanceNCall), FALSE;
K>>        char *ni;
K>>        if( ISNULL(ni=new char[newLimit*size_it]) ) return FALSE;
K>>        if( count != 0 ) memcpy(ni, items, count*size_it);
K>>        delete items; items = ni; limit = newLimit;
K>>    }
K>>    if( i < count )    memmove(items+(i+1)*size_it, items+i*size_it, (count-i)*size_it);
K>>    count++;
K>>    if( item ) memcpy(items+i*size_it, item, size_it);
K>>    else memset(items+i*size_it, 0, size_it);
K>>    return TRUE;
K>>}

K>>


K>>его я не стал искажать — можно и ошибиться


K>>и вы правы — вообще не для хранения объектов с деструктором и/или виртуальными функциями, а что делать идеальные решения не так часто встречаются


Рек>Да. Наверное ты прав и такого типа контейнер сможет работать с некоторыми типами.

Рек>(только с типами, допускающими побитовое копирование — это простые типы (int, double, указатели), и структуры из них).

Рек>А для чего такое ограничение? Что ты получаешь взамен? Сверх эффективную memcpy ?

Рек>Но ведь типы, допускающие побитовое копирование, как правило малы по размерам,
Рек>и сомнительное преимущество memcpy тут никчему. Так что я не вижу никаких преимуществ этого метода.

Рек>Шаблоны тут используются всего лишь для "автоматизации приведения", для скрытия приведения.

Рек>А ведь шаблоны позволяют обойтись совсем без приведения. И позволяют работать с любыми типами.
Рек>Вот что главное!

Рек>Неужели Майерс?


Вообщем то примерно такой подход ещё и Элджер описывал.
Он таким образом скрывал от пользователя реализацию класса.
(у него вообще к программистам крайне негативное отношение )
Жизнь, как игра —
идея паршивая,
графика обалденная...
Re[8]: Это не правильно!
От: Zero  
Дата: 09.04.02 12:42
Оценка:
Да, кстати, стандарт ANSI 1998 Года по книге Страуструпа, позволяет это делать. Даже слово ключевое есть — export;

в h:

template <class T>
class Foo
{
...

};

в .cpp

export template<class T>
Foo::..
{

};

но вот Visuaal Studio 6.0 так не умеет и даже слова такого ключевого не знает.
Re[9]: Это не правильно!
От: Павел Кузнецов  
Дата: 10.04.02 06:29
Оценка:
Z>Да, кстати, стандарт ANSI 1998 Года по книге Страуструпа, позволяет это делать. Даже слово ключевое есть — export;
(...)
Z>но вот Visuaal Studio 6.0 так не умеет и даже слова такого ключевого не знает.

Насколько я знаю, (пока) единственным компилятором, поддерживающим export, является Comeau 4.3 beta.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[9]: Это не правильно!
От: al Россия  
Дата: 10.04.02 10:10
Оценка:
Здравствуйте Zero, Вы писали:

Z>Да, кстати, стандарт ANSI 1998 Года по книге Страуструпа, позволяет это делать. Даже слово ключевое есть — export;


Оперировать в этих вопросах к Страуструпу — пустое дело. Он бы лучше вместо своих "талмудов" сел-бы и написал компилятор,
который все, что он придумал, понимал-бы . А то получается — стандарт отдельно, а реальные программы — отдельно.

P.S.
Интересно, как можно вообще реализовать компиляцию шаблона в реаьный машинный код?


Re[9]: Это не правильно!
От: KA it-knowledge-base.blogspot.com
Дата: 10.04.02 15:26
Оценка:
Здравствуйте Zero, Вы писали:

Z>Да, кстати, стандарт ANSI 1998 Года по книге Страуструпа, позволяет это делать. Даже слово ключевое есть — export;

Кажись, книжку я эту читал, но слова такого не встретил

[skipped]

Z>export template<class T>

Z>Foo::..
Z>{

Z>};

А шо это такое? Похоже на ЭКСПОРТИРОВАНИЕ шаблона из DLL'и
Z>но вот Visuaal Studio 6.0 так не умеет и даже слова такого ключевого не знает.
Так, наверное, никакой компилятор не умеет, если он не интерпретатор

ЗЫ export — слово устаревшее, оно заменено на спецификатор __declspec(dllexport).
//
#import <windows.bas>
class IWindows9x:protected DOS { private: virtual HANDLE EnumClouds()=0; };
Re[10]: Это не правильно!
От: Аноним  
Дата: 11.04.02 07:42
Оценка:
Здравствуйте KA, Вы писали:

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


Z>>Да, кстати, стандарт ANSI 1998 Года по книге Страуструпа, позволяет это делать. Даже слово ключевое есть — export;

KA>Кажись, книжку я эту читал, но слова такого не встретил :(

Глава кажется 13 (о шаблонах), самый последний подпункт.

Z>>export template<class T>

Z>>Foo::..
Z>>{

Z>>};

KA>А шо это такое? Похоже на ЭКСПОРТИРОВАНИЕ шаблона из DLL'и :wow:
Z>>но вот Visuaal Studio 6.0 так не умеет и даже слова такого ключевого не знает.
KA>Так, наверное, никакой компилятор не умеет, если он не интерпретатор ;)

KA>ЗЫ export — слово устаревшее, оно заменено на спецификатор __declspec(dllexport).


Это не тот export! Это именно export template<class T>...!
Re[10]: Это не правильно!
От: Аноним  
Дата: 11.04.02 07:43
Оценка:
Здравствуйте al, Вы писали:

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


Z>>Да, кстати, стандарт ANSI 1998 Года по книге Страуструпа, позволяет это делать. Даже слово ключевое есть — export;


al>Оперировать в этих вопросах к Страуструпу — пустое дело. Он бы лучше вместо своих "талмудов" сел-бы и написал компилятор,

al>который все, что он придумал, понимал-бы :). А то получается — стандарт отдельно, а реальные программы — отдельно.

Ну это я так... вспомнил.

al>P.S.

al>Интересно, как можно вообще реализовать компиляцию шаблона в реаьный машинный код?

А вот это лучше у него самого спросить.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.