Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> частичная специализация функций, не компиляется 
:(
    Опции темы
Jcs
Дата 21.6.2005, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 156
Регистрация: 1.10.2003

Репутация: нет
Всего: нет



Здравствуйте. Не работает код - хотелось бы выяснить причину.
Код

template<int I> struct temp;

template<> struct temp<0>
{
    typedef bool result;
};

template<> struct temp<1>
{
    typedef int result;
};

template<int I> typename temp<I>::result g();

template<> typename temp<0>::result g()
{
    return 0;
}

int main(int argc,char* argv[])
{

    g<0>();
    
    return 0;
}

Для простого случая
Код

template<typename T> T g();

template<> int g()
{return 0;}

вызов
Код

g<int>();
производится нормально. Заранее спасибо.
PM   Вверх
Earnest
Дата 21.6.2005, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Вместо

Код

template<> typename temp<0>::result g()
{
    return 0;
}


пишите просто

Код

temp<0>::result g()
{
    return 0;
}


Функции в C++ частично не специализируются, они просто перегружаются.

А вообще, зачем это? Как я понимаю, вы параметризуете возвращаемый тип, но какова цель? Просто интересно...




--------------------
...
PM   Вверх
Jcs
Дата 21.6.2005, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 156
Регистрация: 1.10.2003

Репутация: нет
Всего: нет



Вообще, изначально в коде вместо temp был список типов, а функция параметризовалась интом, в зависимости от которого возвращался тип находящийся в списке на соответствующей позиции. Задача, для которой все это хочется использовать - извлечение по указателю необходимого типа. Т.е. функция принимает указатель на данные и, в зависимости от шаблонного инта, извлекает из памяти char, short, int и так далее и возвращает его. Перегрузка только по возвращаемому параметру невозвможна. Конечно, так как с помощью частичной специализации пока задача не решается, пришлось вывернуться при помощи перегрузки. Но интересна причина, почему этого не получается сделать. То ли я что-то не так делаю, то ли эта фигня еще не поддерживается компилятором, как например, шаблонные параметры функций по умолчанию.
PM   Вверх
Earnest
Дата 21.6.2005, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Просто код

Код

template<> typename temp<0>::result g()
{
    return 0;
}


сам по себе ошибочен: функция g не является частью шаблона, вы ведь используете только тип. Вот если вы сделаете ее частью шаблона, все будет OK.

Что-то вроде этого:

Код

template<int N> struct temp
{
   typedef bool result;
   static result* get() { ASSERT(0); return 0; }
};

template<> struct temp<1>
{
    typedef int result;
    static result* get()  { return 0;  }
};

void foo()
{
    int* p = temp<1>::get();
}


Это сообщение отредактировал(а) Earnest - 21.6.2005, 20:23


--------------------
...
PM   Вверх
Earnest
Дата 21.6.2005, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Вот еще вариант: разделяем код, чтобы специализировать только возвращаемые типы, тогда для "плоских" типов можно написать общий код, а уж для более сложных - специализировать:

Код

template <int T> struct _selector
{
};

template<> struct _selector<1>
{
    typedef int result;
};

// ... и т.д.

template <int T> struct _extractor
{
    typedef typename _selector<T>::result result;
    
    static result* get(LPBYTE& pMem)
    {
        result* pRes = reinterpret_cast<result*>(pMem);
        pMem += sizeof(result);
        return pRes;
    }
};

void foo()
{
    BYTE Buf[1000];
    LPBYTE pCur = Buf;
    
    int* pInt = _extractor<1>::get(pCur);
}



--------------------
...
PM   Вверх
Jcs
Дата 21.6.2005, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 156
Регистрация: 1.10.2003

Репутация: нет
Всего: нет



Спасибо за идею. Еще немного о задаче. Есть хранилище данных, которое, к примеру считывается из файла, затем создаются сэмплы, каждый из которых знает адрес своих данных в этом хранилище. Сэмплы могут иметь разный размер. Поэтому есть класс базового сэмпла, который знает адрес своих данных и количество каналов (аудио данные, например) и от него наследуется параметризированный интом ребенок, который умеет извлекать данные в удобном для обработки виде. Работают они абсолютно одинаково, поэтому применение частичной специализации, и реализация функции извлечения данных по указателю привели бы к дублированию кода. Частичная специализация только метода извлечения невозможна, т.к. в данный момент это не поддерживается стандартом. Поэтому я хотел для извлечения использовать глобальную функцию, специализировав ее для каждого случая. Не получилось (почему - до сих пор не понимаю). Для решения, как мне кажется, проще привести частичную специализацию к перегрузке, чем заворачивать функцию в шаблонный класс (чтобы не плодить лишних классов). Чтобы избежать появления одинаковых типов параметров, (при 4 и 8 битах на канал возвращается unsigned char) можно использовать вспомогательный класс int2type. Тогда функция извлечения будет выглядеть так
Код


template<int BITS_PER_CHANNEL> struct channel_sample_traits;

template<> struct channel_sample_traits<eFOUR_BITS_PER_CHANNEL>
{
    enum{data_size = 4};
    typedef unsigned char data_type;
};

channel_sample_traits<eFOUR_BITS_PER_CHANNEL>::data_type
retrieve_sample_data(short *psample_data,unsigned short channel_number,                            int2type<eFOUR_BITS_PER_CHANNEL>&)
{...}
channel_sample_traits<eEIGHT_BITS_PER_CHANNEL>::data_type
retrieve_sample_data(short *psample_data,unsigned short channel_number,
            int2type<eEIGHT_BITS_PER_CHANNEL>&)
{...}

Надо попробовать закомпилять частичную специализацию (а не перегрузку) функции в gcc.
PM   Вверх
Earnest
Дата 22.6.2005, 08:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(Jcs @ 21.6.2005, 21:30)
Поэтому я хотел для извлечения использовать глобальную функцию, специализировав ее для каждого случая


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

Частичной специализации функций в стандарте C++ нет, т.к. если бы она была, она делала бы тоже самое, что перегрузка. Ну посудите сами: перегрузка функции - это когда то же имя используется с другими типами/числом параметров.
Короче, частичная специализация и перегрузка делают одно и то же.

Цитата(Jcs @ 21.6.2005, 21:30)
Чтобы избежать появления одинаковых типов параметров, (при 4 и 8 битах на канал возвращается unsigned char) можно использовать вспомогательный класс int2type


Конечно, нормальное решение. Однако в клиентском коде все эти дополнительные параметры не очень уместны. Хочется сделать клиентский код как можно более прозрачным. И тут мы вспоминаем высказывание еще одного гуру (опять не помню кого, но кажется это был Майерс) - любую проблему в программировании можно решить добавлением еще одной прокладки в нужное место. Благодаря Страуструпу и его шаблонам, прокладки в C++ обходятся почти бесплатно (в смысле производительности).

А лишние классы... Чего их экономить? При обобщенном программировании классы всегда плодятся как кролики. Но все это безобразие бесследно исчезает в момент компиляции...

Если данные всегда извлекаются одинаково и меняется только длина, то конечно, разумно написать одну общую функцию, которая будет извлекать данные заданной длины. А из шаблонов вызывать ее с нужным параметром, inline.





--------------------
...
PM   Вверх
Jcs
Дата 22.6.2005, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 156
Регистрация: 1.10.2003

Репутация: нет
Всего: нет



Мне кажется, различия между перегрузкой и частично специализацией все-таки есть.
Данный код компиляется и вызывается нужная функция. Если же разремить перегурженные функции, тогда, естественно, компилятор не сможет определить, какую из версию overload_func вызвать. В случае специализации можно ему помочь)
Код


template<typename T> T g();

template<> int g()
{return 0;}

template<> char g()
{return 0;}

/*int overload_func()
{return 0;}

char overload_func()
{return 0;}*/

int main(int argc,char* argv[])
{

    g<char>();
//    overload_func();
    return 0;
}
.
PM   Вверх
Earnest
Дата 23.6.2005, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Хм... наверно, вы правы... в том что есть разница между специализацией и перегрузкой функций. Только это полная специализация, а не частичная.


--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0517 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.