Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Использование шаблонов


Автор: Lazin 11.1.2008, 14:24
В общем проблема следующая
есть шаблонная функция
Код

template<typename T>
void generic_fn()
{
    ///..сдесь используется тип T
}


тип который подставляется в этот шаблон то-же не так прост...
Код

template <typename T, int n>
struct generic_type
{
   typedef typename ...... Type;
};


для того что бы вызвать ф-ю нуно написать:
Код


generic_fn< generic_type<another_type, 0>::Type >();


нельзя ли как-нибудь упростить запись ?

Код

template<int index>
typedef typename generic_type<another_type, index>::Type Type;


а потом использовать во так:

Код

generic_fn< Type<0> >();
generic_fn< Type<1> >();
generic_fn< Type<2> >();


но это увы невозможно.... противоречит стандарту ;)
как можно поступить в этой ситуации?

Автор: Alek86 11.1.2008, 14:45
ничего умнее наследования не придумал

Код

class CType {};

typedef CType another_type;

template<typename T>
void generic_fn()
  {
  ///..сдесь используется тип T
  }
template <typename T, int n>
struct generic_type {
  typedef T Type;
};

template <int n>
struct Type : public generic_type<another_type, n>::Type {};

int main()
  {
  generic_fn< generic_type<another_type, 0>::Type >();
  generic_fn< Type<0> >();
  }



отследить, что от another_type нельзя наследоваться, можно.
как - описано в книге "Шаблоны C++" (там немало кода, но он собран в библиотеку)


если another_type любой, то умнее\
Код

template <int n>
struct Type {
  typedef typename generic_type<another_type, n>::Type member;
  };

я не придумал

Автор: archimed7592 11.1.2008, 14:47
Самое универсальное решение такого:
Код

template< int index >
struct helper
{
    typedef typename generic_type<another_type, index>::Type type;
};

generic_fn< helper<0>::type >();


Добавлено через 1 минуту и 16 секунд
Цитата(Alek86 @  11.1.2008,  14:45 Найти цитируемый пост)
ничего умнее наследования не придумал

С наследованием проблема в том, что, как минимум нужно продублировать конструкторы...

Автор: Alek86 11.1.2008, 14:51
Цитата(archimed7592 @  11.1.2008,  14:47 Найти цитируемый пост)
С наследованием проблема в том, что, как минимум нужно продублировать конструкторы...


точно

Автор: Lazin 11.1.2008, 14:57
так и думал, что придется еще один что-то подобное городить... не хочется, но придется.
кстати boost::mpl кто-нибудь юзает?

Автор: Alek86 11.1.2008, 15:39
а вот так?

Код

template <int n>
struct Type {
  operator typename generic_type<another_type, n>::Type();
  };

Автор: Earnest 11.1.2008, 16:41
А я бы макрос нарисовала. Что-то вроде:
Код

#define GenericFunc(N) generic_fn<generic_type<another_type, N>::Type >()

Прошу тапками не кидаться, про всякие их ужасы знаю... но все равно пользуюсь, когда очень хочется.


Автор: Lazin 11.1.2008, 16:51
я то-же сначала макрос нарисовал, но с шаблоном получилось не хуже))
сделал примерно так
Цитата(archimed7592 @  11.1.2008,  14:47 Найти цитируемый пост)
Код

generic_fn< helper<0>::type >();

только оприделил класс внутри ф-ии

Автор: Alek86 11.1.2008, 16:52
а шапками можно?

просто поинтересуюсь - а зачем использовать дефайны, когда можно обойтись без них? из-за лени? smile

Добавлено через 2 минуты и 19 секунд
 smile 
а моим способом не надо ::type писать...

Автор: Lazin 11.1.2008, 17:29
Цитата(Alek86 @  11.1.2008,  16:52 Найти цитируемый пост)
а моим способом не надо ::type писать... 

но твой случай в моем случае не подходит, потому-что у меня этот шаблон раскрывается в один из POD типов, и потом передается в std::numeric_limits<T> .
компилятор не смотрит на оператор приведения типа, и пытается инстанциировать шаблон типом Type 

Автор: Alek86 11.1.2008, 17:40
можно примерчик небольшой?
вроде ж, компилятор обязан просматривать все приведения типа

Автор: Lazin 11.1.2008, 20:22
передается в качестве шаблонного параметра Т
Код

    template <typename T, typename state_t>
    bool try_to_set_format(const state_t value, parameter_packer_format_t& format)
    {
        if ( (static_cast<state_t>(std::numeric_limits<T>::min()) <= value) and
             (value <= static_cast<state_t>(std::numeric_limits<T>::max())) )
        {
            format( sizeof(T) );
            return true;
        }
        return false;
    }

template <int n>
struct format_t {
    typedef typename type_at_t<pktime_types, n>::Type type;
}; 

try_to_set_format< format_t<0>::type >(diff, format);


Автор: Alek86 11.1.2008, 21:10
и что, если поменять код (соответственно):

Код

template <int n>
struct format_t {
  operator typename generic_type<another_type, n>::Type ();
  }; 

и
Код

try_to_set_format< format_t<0> >(diff, format);


это не компилируется?

Автор: Lazin 11.1.2008, 21:45
нет, не компилируется, 
код
type_at_t<pktime_types, n>::Type
обычно преобразуется в один из простых типов, int char и тд.

Автор: Cycle 13.1.2008, 01:56
Вроде в новом стандарте С++0х такое уже должно компилится.
Код

template<int index>
typedef typename generic_type<another_type, index>::Type Type;

И вроде в последний gcc включено реализация черновика С++0х. У кого есть такой компилятор (и кто знает с каким ключем нужно компилить) проверте плз. 
P.S. Я понимаю, что автору топика может не к месту использовать gcc по Linux smile Мне просто интересно, можно ли будет так писать в будущем, которое уже не за горами.

Автор: archimed7592 13.1.2008, 07:02
Цитата(Cycle @  13.1.2008,  01:56 Найти цитируемый пост)
Вроде в новом стандарте С++0х такое уже должно компилится.

Да, но, IIRC, нужно typedef typename заменить на using smile.

Автор: UnrealMan 14.1.2008, 14:33
Цитата(Earnest @ 11.1.2008,  16:41)
А я бы макрос нарисовала. Что-то вроде:
Код

#define GenericFunc(N) generic_fn<generic_type<another_type, N>::Type >()

Прошу тапками не кидаться, про всякие их ужасы знаю... но все равно пользуюсь, когда очень хочется.

Если N - шаблонный аргумент, то твой макрос работать не будет.

Автор: Lazin 14.1.2008, 15:37
Цитата(UnrealMan @  14.1.2008,  14:33 Найти цитируемый пост)
Если N - шаблонный аргумент, то твой макрос работать не будет. 

Это еще почему?

Автор: Alek86 14.1.2008, 15:43
в шаблоне могут быть запятые
можно вызывать с помощью (N) а не N

Автор: archimed7592 14.1.2008, 20:49
Цитата(Lazin @  14.1.2008,  15:37 Найти цитируемый пост)
Это еще почему?

typename

Автор: Earnest 14.1.2008, 21:00
Цитата(Alek86 @  14.1.2008,  16:43 Найти цитируемый пост)
в шаблоне могут быть запятые
можно вызывать с помощью (N) а не N 

Да, правильно. Я просто кратко написала. По ходу, в макросах скобки нужно ставить на всех параметрах.

Автор: Alek86 15.1.2008, 11:11
Earnest, не поможет

вызов
Код

GenericFunc(my_template<int, int>::number)


будет невалиден, нужно

Код

GenericFunc((my_template<int, int>::number))

Автор: Lazin 15.1.2008, 11:29
так должно работать
Код

#define GenericFunc(N) generic_fn< typename generic_type<another_type, N>::Type >();
GenericFunc(0);

Автор: Alek86 15.1.2008, 12:45
Цитата(Lazin @  15.1.2008,  11:29 Найти цитируемый пост)
так должно работать

это в ответ на какой пост?
если на мой, то я совсем не то имел в виду
если не на мой - звыняюсь )

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)