Всем привет!
Есть такая производящая функция:
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
Спасибо заранее
Здравствуйте, 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>() ;
}
Здравствуйте, 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>();
Здравствуйте, 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>() ;
Здравствуйте, 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>();
Здравствуйте, 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>>