Re: Aka Tuple
От: Alexey Chen Чили  
Дата: 25.06.05 17:21
Оценка: 54 (4)
Здравствуйте, Alexey Chen, Вы писали:

AC>Заглянул тут в книжку Вандервурда. Там в главе про Tuple, штука такая есть — val<n>. Удобно конечно, но у меня возникла идея, возможно старая как мир. Но таки приведу её на правах прикола.


Я так понял, идея понравилась.

Тогда расскажу продолжение истории...

Кода я попробывал скомпилировать пример в шестой студии, получил весьма неприятное сообщение. Дескать, опреатор [] уже определён. Так пришлось отказатьса от using'а.

Но как же разрешить такую проблему, спросил я себя: Использовать опреаторы базовых шаблонных классов я не могу ибо компилятор их не видит, использовать явное указание компилятору я тоже не могу, он этого не понимает.

Однако, надо писать шаблонный оператор. Оператор, который будет в зависимости от ключа возвращать значение из нужной базы. Ну вы уже понимаете на какую фичу C++ я наткнулся? Правильно, у любой функции обязятельно должн быть задан тип для возвращаемого значения. Автоопределения типа по выраженияю в С++ нет.

Ну что же, значит надо определять тип по ключу. Реально это не сложно, просто рекурсивный шаблон. Но тут шестая студия подставила мне очередную подножку. Ага, она не может вычислять тип возвращаемого значения. Параметр шаблона там стоять может, но элемент другого шаблона параметризированный параметром — нет.

Вот теперь мне стало действительно весело. Нужно было кардинально другое решение, и я его таки родил.

int main()
  {
    Scord< _sf_iHeight, Scord<_sf_fWeight, Scord<_sf_szName> > > s;

    sf_iHeight[s] = 10;
    sf_fWeight[s] = 20.3;
    sf_szName[s] = "jony";

    std::cout
      << sf_iHeight[s]  << std::endl
      << sf_fWeight[s]  << std::endl
      << sf_szName[s]   << std::endl
      << std::endl
      ;
 
    return 0;
  }


Идея вобщем-то простая — пеменять ключ и контейнер местами. Но таки _идея_! Возможно кому-то она поможет выкрабкаться из более тяжёлой ситуации. Чем то это похоже на функции селекторы, но принципиальное отличие в структуре, кторую можно рефлексировать.

Собственно реализация для тех кому интересно. ИМХО, имеет чисто академический интерес.
#define TEGGO_SFIELD(name,type) \
  struct _sf_##name : Sfield< type, _sf_##name > {}; \
  /*static*/ _sf_##name const sf_##name = _sf_##name()

template < class _Key >
  struct _Scord_Value
    {
      typename _Key::_Type sf_value_;
      _Scord_Value() : sf_value_(typename _Key::_Type()) {}
    };

template < class _Tp, class _Self >
  struct Sfield
    {
      typedef _Tp _Type;
      template < class _Value >
        _Type& operator[](_Value &val) const
        {
          return static_cast<_Scord_Value<_Self>&>(val).sf_value_;
        };
    };

struct _Scord_Fake {};

template < class _Key, class _Lst = _Scord_Fake >
  struct Scord : _Scord_Value<_Key>, _Lst 
    {
    };

TEGGO_SFIELD(iHeight, int);
TEGGO_SFIELD(fWeight, float);
TEGGO_SFIELD(szName,  std::string);
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.