Специализация шаблона класса шаблонным параметром
От: NikolayVoronetskiy Россия  
Дата: 29.02.12 06:48
Оценка:
Искомое решение для функции выглядит так:

template<class T> class TestTemplate;
class TestClass;

template<class T> void Foo(){ std::cout << "class\n"; }
template<template<class> class T> void Foo(){std::cout << "template<class>\n";

...

Foo<TestTemplate>();
Foo<TestClass>();


Задача в том, чтобы таким же образом специализировать шаблон класса, грубо говоря:


template<class T> class TestTemplate;
class TestClass;

template<class T> class Bar { static void print(){std::cout << "class\n";} };
template<template <class> class T> class Bar { static void print(){std::cout << "template<class>\n";} };

...

Bar<TestTemplate>::print();
Bar<TestClass>::print();


Не выходит каменный цветок.
Re: Специализация шаблона класса шаблонным параметром
От: wander  
Дата: 29.02.12 07:31
Оценка:
Здравствуйте, NikolayVoronetskiy, Вы писали:

NV> Искомое решение для функции выглядит так:


NV>
NV> template<class T> void Foo(){ std::cout << "class\n"; }
NV> template<template<class> class T> void Foo(){std::cout << "template<class>\n";
NV>

Я так понимаю в этом случае у тебя никакой специализации нет. Зато есть перегрузка.

NV> Задача в том, чтобы таким же образом специализировать шаблон класса, грубо говоря:

NV>
NV> template<class T> class Bar { static void print(){std::cout << "class\n";} };
NV> template<template <class> class T> class Bar { static void print(){std::cout << "template<class>\n";} };
NV>


ИМХО, не получится так. Если мы специализируем первый вариант (где передается тип T), то параметром в любом случае будет ожидаться тип. Если мы специализируем второй вариант (где передается шаблон), то параметром в любом случае будет ожидаться шаблон. Чтобы превратить шаблон в тип, нужно его инстанцировать. Иными словами аргументы шаблона в такой ситуации нужно будет тоже передать так или иначе.
avalon 1.0rc3 build 426, zlib 1.2.3
Re: Специализация шаблона класса шаблонным параметром
От: Кодт Россия  
Дата: 29.02.12 07:53
Оценка: 6 (2)
Здравствуйте, NikolayVoronetskiy, Вы писали:

NV>Не выходит каменный цветок.


По моему разумению, шаблонные параметры лучше оборачивать. Потому что они жёстко фиксируют сигнатуру шаблона.
Вот например,
template< template<typename>class T > struct Foo { T<int> ti; };

// кандидаты в параметры для Foo
template<class X> struct A {};
template<class X, class Y=void> struct B {};

// проверяем с одним параметром
A<int> ai;
B<int> bi;

// пытаемся подставить
Foo<A> fa;
Foo<B> fb; // фигушки

Но если мы внесём промежуточный слой в виде метафункции, всё будет хорошо
template<class T> struct def_type { typedef T type; };

struct MakeA  { template<class X> struct make : def_type< A<X> > {}; };
struct MakeB1 { template<class X> struct make : def_type< B<X> > {}; }; // можем использовать умолчания целевого шаблона
struct MakeB2 { template<class X, class Y=void> struct make : def_type< B<X,Y> > {}; }; // а можем и свои умолчания вводить

template<class Maker> struct Foo
{
  typename Maker::template make<int>::type ti;
};

Foo<MakeA> fa;
Foo<MakeB1> fb1;
Foo<MakeB2> fb2;
Перекуём баги на фичи!
Re: Специализация шаблона класса шаблонным параметром
От: Lucky Cat  
Дата: 29.02.12 11:15
Оценка: 1 (1)
Здравствуйте, NikolayVoronetskiy, Вы писали:

NV>Задача в том, чтобы таким же образом специализировать шаблон класса, грубо говоря:


Может нужно не шаблон класса специализировать, а специализировать шаблонную функцию-член класса?

template<class T> class TestTemplate {};
class TestClass {};

class Bar
{
public:
    static void print()
    {
        std::cout << "class\n";
    };
    template<class T> static void Foo()
    {
        std::cout << "class\n";
    };
    template<template<class> class T> static void Foo()
    {
        std::cout << "template<class>\n";
    };
};

int main()
{
    Bar::Foo<TestClass>();
    Bar::Foo<TestTemplate>();
    return 0;
}
Re[2]: Специализация шаблона класса шаблонным параметром
От: NikolayVoronetskiy Россия  
Дата: 29.02.12 12:16
Оценка:
Здравствуйте, wander, Вы писали:

W>Я так понимаю в этом случае у тебя никакой специализации нет. Зато есть перегрузка.


Да перегрузка, я просто проиллюстрировал чего конкретно хочется добиться концептуально, мне фактически нужна не специализация, а именно "перегрузка" шаблона, те 2 шаблона с одинаковым именем, но разным набором параметров

W>ИМХО, не получится так. Если мы специализируем первый вариант (где передается тип T), то параметром в любом случае будет ожидаться тип. Если мы специализируем второй вариант (где передается шаблон), то параметром в любом случае будет ожидаться шаблон. Чтобы превратить шаблон в тип, нужно его инстанцировать. Иными словами аргументы шаблона в такой ситуации нужно будет тоже передать так или иначе.


Пока именно искомого решения действительно не найдено.
Re[2]: Специализация шаблона класса шаблонным параметром
От: NikolayVoronetskiy Россия  
Дата: 29.02.12 12:19
Оценка:
Спасибо за отклик! Да в какой-то степени это является решением, к сожалению лучше пока ничего не нашёл.
Re[2]: Специализация шаблона класса шаблонным параметром
От: NikolayVoronetskiy Россия  
Дата: 29.02.12 12:22
Оценка:
Здравствуйте, Lucky Cat, Вы писали:

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


NV>>Задача в том, чтобы таким же образом специализировать шаблон класса, грубо говоря:


LC>Может нужно не шаблон класса специализировать, а специализировать шаблонную функцию-член класса?


Нет к сожалению мне нужна не функция, а мне нужно следующее если говорить конкретно:


template<class C, class T> class Bar            { typedef T Type; };
template<class C, template <class> class T> class Bar    { typedef T<C> Type; };
Re[3]: Специализация шаблона класса шаблонным параметром
От: night beast СССР  
Дата: 29.02.12 15:36
Оценка:
Здравствуйте, NikolayVoronetskiy, Вы писали:

NV>Спасибо за отклик! Да в какой-то степени это является решением, к сожалению лучше пока ничего не нашёл.


лучше и не надо.
более подробно смотри "C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond"
Re[3]: Специализация шаблона класса шаблонным параметром
От: Кодт Россия  
Дата: 29.02.12 21:19
Оценка:
Здравствуйте, NikolayVoronetskiy, Вы писали:

NV>Спасибо за отклик! Да в какой-то степени это является решением, к сожалению лучше пока ничего не нашёл.


Да, я ж забыл — надо было специализировать, в зависимости от арности метафункции.
Придётся немного вывернуться.
По-прежнему, будем в метафункцию передавать параметры одного и того же вида (kind) — а именно, конкретные классы.
Различать же станем по этим классам. Причём со всей мощью С++ного паттерн-матчинга!
// пишем обёртки
template<class T> struct wrap_final {};
template<template<typename>class T> struct wrap_unary {};

// пишем нашу метафункцию
template<class C, class T>                   struct rebinder                     : def_type< T    > {};
template<class C, class T>                   struct rebinder< C, wrap_final<T> > : def_type< T    > {};
template<class C, template<typename>class T> struct rebinder< C, wrap_unary<T> > : def_type< T<C> > {};

template<class T> void foo(T) { printf("%s\n", __PRETTY_FUNCTION__); }

struct A {};
template<class T> struct B {};

int main()
{
  (foo( rebinder< int, A             >::type() )); // foo<A>
  (foo( rebinder< int, wrap_final<A> >::type() )); // foo<A>
  (foo( rebinder< int, wrap_unary<B> >::type() )); // foo<B<int>>
}

Заметим: wrap_unary<T> имеет вид "class", а не "template<class>class". Но его можно сопоставить — извлечь его параметр искомого вида.

В принципе, основной шаблон можно было и не определять, оставив только две специализации. Ибо нефиг смешивать голые и обёрнутые параметры.
Или можно выкинуть специализацию для wrap_final — пусть вместо этого работает основной шаблон с голым параметром.
Перекуём баги на фичи!
Re[3]: Специализация шаблона класса шаблонным параметром
От: rg45 СССР  
Дата: 29.02.12 22:21
Оценка:
Здравствуйте, NikolayVoronetskiy, Вы писали:

NV>>>Задача в том, чтобы таким же образом специализировать шаблон класса, грубо говоря:

LC>>Может нужно не шаблон класса специализировать, а специализировать шаблонную функцию-член класса?

NV>Нет к сожалению мне нужна не функция, а мне нужно следующее если говорить конкретно:


NV>
NV>template<class C, class T> class Bar            { typedef T Type; };
NV>template<class C, template <class> class T> class Bar    { typedef T<C> Type; };
NV>


Возможно, все проще?

// The primary template
template<class T> 
class Bar            
{ 
public:
  typedef T Type; 
};

// A partial specialization for templates with single type parameter
template<class C, template <class> class T> 
class Bar<T<C> >    
{ 
public:
  typedef T<C> Type; 
};

// Use cases
class TestClass { };
template<class T> class TestTemplate { };

Bar<TestClass>::Type a;
Bar<TestTemplate<int> >::Type b;
--
Справедливость выше закона. А человечность выше справедливости.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.