реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Частичная специализация методов в шаблоне класса, С++
jorikdima
сообщение Jun 22 2010, 19:15
Сообщение #1


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 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. Как это описать?
Спасибо.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Jun 22 2010, 19:51
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Параметры шаблона должны быть определены на момент компиляции, посему параметры шаблона: типы, целые числа и enum.
Go to the top of the page
 
+Quote Post
shreck
сообщение Jun 23 2010, 01:45
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 327
Регистрация: 24-06-06
Из: Томск
Пользователь №: 18 328



Погуглите "Симуляция частичной специализации". Будет много информации. Но при отсутствии поддержки компилятора, реализация частичной специализации будет не такой изящной, как вам хотелось бы.
Go to the top of the page
 
+Quote Post
dxp
сообщение Jun 23 2010, 05:20
Сообщение #4


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> будет использоваться эта специализированная функция.

Вообще, частичная специализация просится в этот шаблон для работы с указателями. Это классический пример. Но все руки никак не дойдут написать это и выложить. smile.gif


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Jun 23 2010, 07:06
Сообщение #5


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 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 , а реализацию остальных методов возложить на компилятор на общих основаниях. Тут либо не рыпаться, либо переписывать ВСЕ методы класса (вплоть до копипаста) для конкретного набора параметров. Странно, почему так...
Go to the top of the page
 
+Quote Post
dxp
сообщение Jun 23 2010, 08:22
Сообщение #6


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);
    ...
};

Но тут придется все члены определять.

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


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Jun 23 2010, 08:52
Сообщение #7


тут может быть ваша реклама
*****

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



Спасибо большое за ответы, dxp. Буду идти каким-нибудь другим путем.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 14:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01426 секунд с 7
ELECTRONIX ©2004-2016