Template template arguments
От: Diamondus  
Дата: 10.07.08 14:55
Оценка:
Всем привет!

Есть такая производящая функция:
struct Creator
{
    template <template <int> class T, int S>
    static T<S> * Create() { return new T<S>; }
};

Используется примерно так:
class B {} ;

template <int I>
class C: public B {} ;

void foo()
{
    B * p = Creator::Create<C, 1>() ;
}

Я хочу обобщить ее на случай произвольного типа параметра, делаю так:
template <class PT>
struct Creator
{
    template <template <PT> class T, PT S>
    static T<S> * Create() { return new T<S>; }
};

void foo()
{
    B * p = Creator<int>::Create<C, 1>() ;
// error C3208: 'Creator<PT>::Create' : template parameter list for class template 'C' does not match template parameter list for template template parameter 'T'
//        with
//        [
//            PT=int
//        ]
//        .\src\hello.cpp(30) : see declaration of 'Creator<PT>::Create'
//        with
//        [
//            PT=int
//        ]
}

Пробовал также так:
struct Creator
{
    template <class PT, template <PT> class T, PT S>
    static T<S> * Create() { return new T<S>; }
};

void foo()
{
    B * p = Creator::Create<int, C, 1>() ;
// error C3208: 'Creator::Create' : template parameter list for class template 'C' does not match template parameter list for template template parameter 'T'
}

Возможно ли сделать такое средствами языка C++ и как именно?
Компилятор MSVS2008

Спасибо заранее
template metaprogramming
Re: Template template arguments
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 10.07.08 15:20
Оценка:
Здравствуйте, Diamondus, Вы писали:

D>Я хочу обобщить ее на случай произвольного типа параметра


Попробуй так:

struct Creator
{
    template <template <class> class T, class S>
    static T<S> * Create() { return new T<S>; }
};


class B {} ;

template <class I>
class C: public B {} ;

struct S { };

void foo()
{
    B * p = Creator::Create<C, S>() ;
}
Re[2]: Template template arguments
От: Diamondus  
Дата: 10.07.08 15:33
Оценка:
Здравствуйте, Alxndr, Вы писали:

A>Здравствуйте, Diamondus, Вы писали:


D>>Я хочу обобщить ее на случай произвольного типа параметра


A>Попробуй так:


A>
A>struct Creator
A>{
A>    template <template <class> class T, class S>
A>    static T<S> * Create() { return new T<S>; }
A>};


A>class B {} ;

A>template <class I>
A>class C: public B {} ;

A>struct S { };

A>void foo()
A>{
A>    B * p = Creator::Create<C, S>() ;
A>}
A>


Нененене. Этот вариант, конечно, работает, но мне нужно, чтобы в template<int> class T можно было подставлять не тип, а целочисленное значение произвольного типа, в общем, non-type аргумент:
enum TMyEnum { EOne, ETwo, EThree };

template <TMyEnum I>
class D: public B {} ;

B * p = Creator<TMyEnum>::Create<D, ETwo>();
Re: Template template arguments
От: Юрий Жмеренецкий ICQ 380412032
Дата: 10.07.08 15:45
Оценка: 1 (1)
Здравствуйте, Diamondus, Вы писали:
...
class B {} ;

template <int I>
class C: public B {} ;

struct makeC 
{
  template<int i> struct apply {
    typedef C<i> type;
  };
};

struct Creator
{
  template <class f, class arg, arg val>
  static typename f::apply<val>::type* Create(){
    return new f::apply<val>::type(); 
  }
};

//...
B * p = Creator::Create<makeC, int, 1>() ;
Re: Template template arguments
От: Юрий Жмеренецкий ICQ 380412032
Дата: 10.07.08 15:57
Оценка: 1 (1)
Здравствуйте, Diamondus, Вы писали:
...
Или даже так:
struct C
{ 
  template<int i>
  struct impl : public B
  {
  };
};

struct Creator
{
  template <class f, class arg, arg val>
  static typename f::impl<val>* Create(){
    return new f::impl<val>(); 
  }
};
//..
B * p = Creator::Create<C, int, 1>();
Re: Template template arguments
От: Кодт Россия  
Дата: 10.07.08 16:06
Оценка: 5 (2)
Здравствуйте, Diamondus, Вы писали:

D>Компилятор MSVS2008


Comeau 4.3.9 (online) компилирует, gcc 3.4.4 (cygwin) и VC2005 и 2008 обламываются.
Неполная реализация стандарта?

D>Возможно ли сделать такое средствами языка C++ и как именно?


Попробуй отказаться от шаблона-параметра. Точнее, оберни его:
// метафункция идентичности
// это чтоб сто раз не писать в метафункциях { typedef bla-bla-bla type; }
template<class T> struct identity { typedef T type; };


// тут всё как обычно
struct B {};
template<int S> struct C : B {};

// а вот здесь добавляем обёртку для метафункции int -> C<*>
struct generate_C
{
    template<int S> struct apply : identity< C<S> > {};
};


// собственно, вот
template<class PT> // можно перетащить этот параметр и вниз...
struct Creator
{
    template<class T, PT S> // ...сюда
    static
    typename T::template apply<S>::type * // громоздко, конечно, зато работает
    Create() { return new typename T::template apply<S>::type(); }
};

void foo()
{
    Creator<int>::Create<generate_C, 123>();
}
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.