Шаблон функции как параметр шаблона
От: Аноним  
Дата: 24.01.04 22:27
Оценка:
Доброе время суток.

Я работаю с CodeWarrior 8.3 на Macintosh и столкнулся с такой проблемой: как передать шаблон функции как параметр шаблона другой функции или класса?
Немного истории . Есть правильно работающий код:


// TList - Loki::Typelist<>
// конвертирует тип из списка типов в адрес конкретизации 
// функции FunctionsOwner::Function1 этим типом
template <class TList, class FunctionsOwner>
struct TypeListToFunctionMap
{
  void Convert(FunctionsOwner::Map& map)
  {
    ...
    typedef TList::Head SomeType;
    map[i] = &FunctionsOwner::Function1<SomeType>;
    ....
  }
};

class CFunctionsOwner
{
  publuc:
     typedef void (CFunctionsOwner::*TMapElement)();
     TMapElement m_Map[10];
     template <typename T>
     void Function1()
     {
       ...
     }
};



Вызов такой:

CFunctionsOwner functions;
TypeListToFunctionMap<MyList, CFunctionsOwner>::Convert(functions.m_Map);


Все было хорошо, пока не понадобилась map для другой функции Function2(). Хотелось бы получить что-то такое:

TypeListToFunctionMap<MyList, CFunctionsOwner::Function1>::Convert(functions.m_Map1);
TypeListToFunctionMap<MyList, CFunctionsOwner::Function2>::Convert(functions.m_Map2);


Но компилятор ругается по поводу CFunctionsOwner::Function1 — declaration syntax error
Отсюда вопрос: возтожно ли вообще передать как паратетр шаблона неконкретизированный шаблон функции (с шаблоном класса все котпилируется )?

Заранее благодарен, Сергей.
Re: Шаблон функции как параметр шаблона
От: Кодт Россия  
Дата: 25.01.04 03:44
Оценка:
Здравствуйте, <Аноним>, Вы писали:

<>

Вообще, шаблон может быть параметризован шаблоном.
template< class A, template<class> class B >
class YourTemplateClass
{
    typedef B<int> bint_type;
};

class SetOfBTypes
{
    template<class T> class BFirst { ... };
    template<class T> class BSecond { ... };
    // от этих классов требуется, чтобы они были моделью "шаблон с одним параметром - классом"
    
    typedef YourTemplateClass< char, BFirst > FirstClass;
};

но не все компиляторы это понимают и любят.

Выход из ситуации — это упрятывание шаблона вглубь.
template< class A, class BWrapper >
{
    typedef typename BWrapper::B<int> bint_type;
};

class SetOfBTypes
{
    struct BFirst
    { template<class T> class B { ... }; };
    struct BSecond
    { template<class T> class B { ... }; };
    // от этих классов требуется, чтобы они были моделью "класс с публичным шаблонным типом B<class>"
    
    typedef YourTemplateClass< char, BFirst > FirstClass;
};
... << RSDN@Home 1.1.0 stable >>
Перекуём баги на фичи!
Re[2]: Шаблон функции как параметр шаблона
От: _Macintosh_ Израиль  
Дата: 25.01.04 17:46
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Вообще, шаблон может быть параметризован шаблоном.

К>[c]
К>template< class A, template<class> class B >
К>class YourTemplateClass
К>{
К> typedef B<int> bint_type;
К>};

Большое спасибо за совет, но, видимо я плохо задал вопрос . Вариант передачи шаблона класса мною рассматривался и принят как резервный. Вопрос в другом: как передать (и объявить) в качестве параметра шаблона шаблон функции?

Задача алгоритма TypeListToFunctionMap заполнить map объектами, которые являются конкретизацией какого-то шаблона. Если объкт есть функция, то и шаблон должен быть шаблоном функции. И, если язык позволякт, то зачем эту функцию зяаварачивать в класс.

Но, видно, не судьба. Сегодня друг прислал книжку C++ Templates: The Complete Guide By David Vandevoorde, Nicolai M. Josuttis. Вот, что умные дядьки пишут :

8.3.4 Template Template Arguments
A template template argument must be a class template with parameters that exactly match the parameters of the template template parameter it substitutes.


Так что, всем спасибо. Пошел писать классы-обвертки
Re[3]: Шаблон функции как параметр шаблона
От: MaximE Великобритания  
Дата: 25.01.04 23:09
Оценка:
_Macintosh_ wrote:

> Большое спасибо за совет, но, видимо я плохо задал вопрос . Вариант передачи шаблона класса мною рассматривался и принят как резервный. Вопрос в другом: как передать (и объявить) в качестве параметра шаблона шаблон функции?


Никак

> Задача алгоритма TypeListToFunctionMap заполнить map объектами, которые являются конкретизацией какого-то шаблона. Если объкт есть функция, то и шаблон должен быть шаблоном функции. И, если язык позволякт, то зачем эту функцию зяаварачивать в класс.

[]

> Так что, всем спасибо. Пошел писать классы-обвертки


Описал бы не так узко, а big picture, может нашлось бы более интересное решение твоей задачи.

--
Maxim Egorushkin
MetaCommunications Engineering
http://www.meta-comm.com/engineering/
Posted via RSDN NNTP Server 1.8 beta
Re: Шаблон функции как параметр шаблона
От: Lorenzo_LAMAS  
Дата: 26.01.04 07:42
Оценка:
Может я не в кассу — лень разбираться. Но если просто посмотреть на твой код, то я в нем заметил две ошибки, исправь их — может заработает

А>struct TypeListToFunctionMap
А>{
А>  void Convert(FunctionsOwner::Map& map)
А>  {
А>    ...
А>    typedef typenameTList::Head SomeType;
А>    map[i] = &FunctionsOwner::template Function1<SomeType>;
А>    ....
А>  }
А>};
Of course, the code must be complete enough to compile and link.
Re[3]: Шаблон функции как параметр шаблона
От: LaptevVV Россия  
Дата: 26.01.04 07:47
Оценка:
Здравствуйте, _Macintosh_, Вы писали:

_M_>Но, видно, не судьба. Сегодня друг прислал книжку C++ Templates: The Complete Guide By David Vandevoorde, Nicolai M. Josuttis. Вот, что умные дядьки пишут :

Она есть на русском — смотри рецензию на сайте.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Шаблон функции как параметр шаблона
От: _Macintosh_ Израиль  
Дата: 26.01.04 18:52
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Может я не в кассу — лень разбираться. Но если просто посмотреть на твой код, то я в нем заметил две ошибки, исправь их — может заработает


L_L>
А>>struct TypeListToFunctionMap
А>>{
А>>  void Convert(FunctionsOwner::Map& map)
А>>  {
А>>    ...
А>>    typedef typenameTList::Head SomeType;
А>>    map[i] = &FunctionsOwner::template Function1<SomeType>;
А>>    ....
А>>  }
А>>};
L_L>


Спасибо, обязательно добавлю. Но это, действительно, не очень существенно, т.к. это работающий код (во всяком случае, на CodeWarrior`е). Мне не нравиться, что TypeListToFunctionMap жестко привязан к имени шаблона FunctionsOwner::template Function1<SomeType>. Хотелось его в параметры шаблона затолкать, но напрямую нельзя... А жаль.
Re[4]: Шаблон Property Manager
От: _Macintosh_ Израиль  
Дата: 26.01.04 20:34
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Описал бы не так узко, а big picture, может нашлось бы более интересное решение твоей задачи.


Я старался акцентировать внимание на вопросе, который, собственно, теоретический. Хотя, по большому счету, это почти вся задача (мелкомасштабный я какой-то ). По историческим причинам в проекте, в котором я учавствую, принято выставлять наружу из библиотек С-интерфейс. И чтобы не раздувать интерфейс, всякие параметры передаются через Get/SetParameter(long paramID, void* dataStruct, size_t dataStructSize).
Со стороны библиотеки сидит switch по ID, переадресующий вызов куда следует. В общем, классика . Причем, набор параметров меняется в зависимости от режима работы библиотеки. Я хочу это автоматизировать примерно так:

Шаблон для определения внутреннего(библиотечного) типа параметра
template <class SimpleParamType, int ParamID>
struct SParam
{
    // внешний(пользовательский) тип параметра
    typedef SimpleParamType TUserParamType;
    // ID для доступа
    enum {k_ParamID = ParamID};
    TUserParamType m_Param;
    TUserParamType GetUserParam() const
    {
       return m_Param;
    }
};

typedef SParam<float, 1> SParam1;
typedef SParam<long, 2> SParam2;


Это конкретный класс, определяющий набор параметров для конкретного режима работы.
class CParamsHolder
{
  public:
    // текущий набор параметрав
    typedef TYPELIST_2(SParam1, SParam2) TParamList;

    long GetParam(SParam1& param) const
    {
      ...
    }

    long GetParam(SParam2& param) const
    {
      ...
    }
};


Это шаблон диспетчера, конкретизирующийся текущим набором параметров. Шаблон TypelistToFuncMap описан в предыдущем посте.
class IParamsManager
{
   long GetParameter(long paramID, void* buf, size_t bufSize) = 0;
};

template <class ParamsHolder>
class CParamsManager : piblic IParamsManaget
{
    public:
      typedef (CParamsManager<ParamsHolder>::*TCall)(long paramID, void* buf, size_t bufSize);
      typedef TCall TCallMap[k_TotalParams]; //для упрощения кода
    private:
      ParamsHolder m_ParamsHolder;
      TCallMap m_CallMap;
    public:
      
      CParamsManager()
      {
         memset(m_CallMap, 0, sizeof(m_CallMap));

         // Конвертируем список типов в набор конкретизаций GetUserParameter<...> 
         TypelistToFuncMap<ParamsHolder::TParamList, 
                            CParamsManager<ParamsHolder> 
                           >::Convert(m_CallMap);
      }

      template <class InternalParamType>
      long GetUserParameter(long paramID, void* buf, size_t bufSize)
      {
         long retVal = -1;
         if(bufSize == sizeof(InternalParamType::TUserParamType))
         {
            InternalParamType param;
            retVal = m_ParamsHolder.GetParam(param);
            *(static_cast<InternalParamType::TUserParamType*>(buf)) = param.GetUserParam();
         }
         return retVal;
         
      }
      
      long GetParameter(long paramID, void* buf, size_t bufSize)
      {
         TCall theCall = CallMap[paramID];
         if(0 == theCall)
            return -1;
         else
            return (this->*theCall)(buf, bufSize);
      }

};

Ну и все, вроде. Если кто-то прочитает эту строчку, то наверняка предложит более красивое решенее .
Re[5]: Шаблон Property Manager
От: _Macintosh_ Израиль  
Дата: 28.01.04 06:57
Оценка:
Приятно видеть, что дизайн Property Manager`а не вызывает нереканий . Может он и вправду не такой уж хреновый ?
Re[5]: Шаблон Property Manager
От: MaximE Великобритания  
Дата: 28.01.04 08:17
Оценка:
_Macintosh_ wrote:

> Я старался акцентировать внимание на вопросе, который, собственно, теоретический. Хотя, по большому счету, это почти вся задача (мелкомасштабный я какой-то ). По историческим причинам в проекте, в котором я учавствую, принято выставлять наружу из библиотек С-интерфейс. И чтобы не раздувать интерфейс, всякие параметры передаются через Get/SetParameter(long paramID, void* dataStruct, size_t dataStructSize).

> Со стороны библиотеки сидит switch по ID, переадресующий вызов куда следует. В общем, классика . Причем, набор параметров меняется в зависимости от режима работы библиотеки. Я хочу это автоматизировать примерно так:

[]

Если я правильно понял, основная сложность твоей задачи — это преобразование run-time значения в compile time сущность (тип или константу). Конкретно здесь — long в тип.

Здесь эта задача решена посредством генерации массива указателей специализаций фунции по списку типов. Решение хорошее

--
Maxim Egorushkin
MetaCommunications Engineering
http://www.meta-comm.com/engineering/
Posted via RSDN NNTP Server 1.8 beta
Re[6]: Шаблон Property Manager
От: _Macintosh_ Израиль  
Дата: 28.01.04 20:44
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Если я правильно понял, основная сложность твоей задачи — это преобразование run-time значения в compile time сущность (тип или константу). Конкретно здесь — long в тип.


ME>Здесь эта задача решена посредством генерации массива указателей специализаций фунции по списку типов. Решение хорошее


Благодарю за комплемент . Мне кажется, что управлене доступом к свойствам и параметрам — задача очень древняя. Может быть есть какие-то стандартные решения?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.