|
|
  |
Частичная специализация методов в шаблоне класса, С++ |
|
|
|
Jun 22 2010, 19:15
|

тут может быть ваша реклама
    
Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280

|
Здравствуйте. Никогда не любил шаблоны, видимо потому что спал, когда на лекциях про них рассказывали, либо синтаксис просто жутко сложен. В общем сейчас нужна подсказка по ним. Использую scmRTOS, там шаблоы используются часто, в том чиле и для реализации кольцевого буфера. Код template<typename T, word Size, typename S = byte> class ring_buffer { public: ring_buffer() : Count(0), First(0), Last(0) { }
//---------------------------------------------------------------- // // Data transfer functions // bool write(const T* data, const S cnt); void read(T* const data, const S cnt); ............................................................ У шаблона 3 параметра: тип хранимых данных, размер буфера и тип индексов. Есть функции записи и чтения, которые тоже реализованы шаблоном: Код template<typename T, word Size, typename S> void usr::ring_buffer<T, Size, S>::read(T* data, const S cnt) { } Так вот, я могу специализировать этот метод для конкретных параметров шаблона, например: Код template<> void usr::ring_buffer<int, 100, int>::read(int* data, const int cnt) { } И так оно работает (по крайней мере компилируется). Но! В данном случае, такой параметр шаблона как размер буфера, я бы хотел так и оставить параметом, специализировать я хочу только тип данных и тип индексов. Хотел бы написать что-то вроде: Код template<> void usr::ring_buffer<int, Size, int>::read(int* data, const int cnt) { } Но говорит, что не знает что такое Size. Я видел про специализацию шаблонов классов, но на сколько я понял, это более глобально, чем нужно мне. Не придется ли мне там переопределять все методы и поля класса? Мне-то нужно только read и write определить для частного случая хранения int. Как это описать? Спасибо.
|
|
|
|
|
Jun 23 2010, 05:20
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(jorikdima @ Jun 23 2010, 02:15)  Так вот, я могу специализировать этот метод для конкретных параметров шаблона, например: Код template<> void usr::ring_buffer<int, 100, int>::read(int* data, const int cnt) { } И так оно работает (по крайней мере компилируется). Это полная специализация шаблона. Т.е. по сути это просто отдельная полная реализация класса со всеми вытекающими - рост размера программы. Цитата(jorikdima @ Jun 23 2010, 02:15)  Но! В данном случае, такой параметр шаблона как размер буфера, я бы хотел так и оставить параметом, специализировать я хочу только тип данных и тип индексов. Хотел бы написать что-то вроде: Код template<> void usr::ring_buffer<int, Size, int>::read(int* data, const int cnt) { } Но говорит, что не знает что такое Size. Тут синтаксическая ошибка. Частичная специализация задается как обычное определение шаблона за исключением того, что в аргументах указываются конкретные типы: Код template<typename T, word Size, typename S> void usr::ring_buffer<int, Size, int>::read(T* data, const S cnt) { } В этом случае для типа, создаваемого из шаблона с параметрами <int, unsigned short, int> будет использоваться эта специализированная функция. Вообще, частичная специализация просится в этот шаблон для работы с указателями. Это классический пример. Но все руки никак не дойдут написать это и выложить.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Jun 23 2010, 07:06
|

тут может быть ваша реклама
    
Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280

|
Спасибо за ответы. DXP, я пробовал тот синтаксис, что Вы привели, но к сожалению либо что-то недопонимаю, либо просто ошибка. Для примера я создал в VisualStudio проект, чтоб абстрагироваться от остального кода. Собственно там всего два файла: .h Код template<typename T, int Size, typename S = char> class ring_buffer { public: ring_buffer(): Count(0), First(0), Last(0) { }
bool write(const T* data, const S cnt); void read(T* const data, const S cnt); private: S Count; S First; S Last; T Buf[Size]; }; .c Код #include "t1.h"
template<typename T, int Size, typename S> bool ring_buffer<T, Size, S>::write(const T* data, const S cnt) { return true; }
template<typename T, int Size, typename S> void ring_buffer<T, Size, S>::read(T* data, const S cnt) { }
template<typename T, int Size, typename S> void ring_buffer<char, Size, char>::read(T* data, const S cnt) { }
ring_buffer<char, 10> tmp; void main() {
tmp.write("ddsdsd", 7);
} Студия говорит: Цитата d:\mydocs\visual studio 2008\projects\templ\t1.cpp(17) : error C3860: template argument list following class template name must list parameters in the order used in template parameter list 1>d:\mydocs\visual studio 2008\projects\templ\t1.cpp(17) : error C2995: 'void ring_buffer<T,Size,S>::read(T *const ,const S)' : function template has already been defined 1> d:\mydocs\visual studio 2008\projects\templ\t1.h(10) : see declaration of 'ring_buffer<T,Size,S>::read' Судя по всему, нельзя сделать так как я хочу. А именно, для конкретного набора параметров переопределить только два метода write и read , а реализацию остальных методов возложить на компилятор на общих основаниях. Тут либо не рыпаться, либо переписывать ВСЕ методы класса (вплоть до копипаста) для конкретного набора параметров. Странно, почему так...
|
|
|
|
|
Jun 23 2010, 08:22
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(jorikdima @ Jun 23 2010, 14:06)  Судя по всему, нельзя сделать так как я хочу. А именно, для конкретного набора параметров переопределить только два метода write и read , а реализацию остальных методов возложить на компилятор на общих основаниях. Тут либо не рыпаться, либо переписывать ВСЕ методы класса (вплоть до копипаста) для конкретного набора параметров. Странно, почему так... Да, тут с вашей хотелкой засада. Вам по сути нужна полная специализация функции-члена, но такая специализация допускается только для шаблонов с одним параметром (а там три). Второй вариант - частичная специализация шаблона класса: Код template<word Size> class ring_buffer<int, Size, int> { public: ... bool write(const int* data, const int cnt); void read(int* const data, const int cnt); ... }; Но тут придется все члены определять. Почему так? Трудный (для меня) вопрос. Наверное, потому, что специализация - это всегда другая реализация, поэтому она должна быть информационно самостоятельной. Цель специализации - предоставить статический полиморфизм: использующий код один и тот же, а реализации подставляются разные.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|