С++, как лучше реализовать темплейт на темплейт

Phoenix

Пусть есть классы, которых хранят некие данные (это могут быть хэши, списки и т.п.)
 


template <bool is_desc>
class Unit
{
int value1_;
int value2_;
int get_maxelementh
{
if(is_desc && value1_ > value2_)
return value1_;
if(!is_desc && value1_ < value2_)
return value1_;
return value2_;
};
};

template <typename children_t, bool is_desc, int mod>
class Hash
{
int get_maxelementh;
} ;

template <typename children_t, bool is_desc, int size>
class List
{
int get_maxelementh;
} ;


Далее всё это используется в некотором классе вот так
 

template <typename asc_t, typename desk_t>
class Storage
{
asc_t left;
desc_t rigth;
}


а чтобы создать объект такого Storage приходится писать вот так
 



Storage <Hash<List<Unit<true>, true, 500>, true, 10>,
Hash<List<Unit<false>, false, 500>, false, 10> my_storage



Было бы идеально, если можно было бы написать
 


templtae <metatypename<bool T> substorage_t>
class Storage
{
substorage_t<true> left;
substorage_t<false> left;

}

Storage <Hash<List<Unit<T>, T, 500>, T, 10>> my_storage;

Т.е. тип доопределяется уже внутри класса.
как такое можно провернуть?

smit1

Мало что смог понять. Тебе вот эта конструкция нужна?

template<template<bool B> class C> class Storage
{
C<false> left;
C<true> right;
};

Phoenix

Да, именно так хочу. А как storage создать после этого?

smit1


template<bool B> class Container
{
//
};

Storage<Container> storage;

Phoenix

так Container должен быть типа Hash<List<Hash....>>>> , а так я только некоторый член Container смогу сделать этого типа и придётся обёртку делать
что-то типа
typedef template<bool T> <Hash<List<Unit<T>, T, 500>, T, 10> Container;

Phoenix

всё равно не получается. Если использовать хоть где-нибдь Hash, то нужно указать один из его параметров - а их как раз не хочется указывать
 

#include <stdio.h>

template<bool is_desc>
class Unit
{
int func
{
if(is_desc) return 1;
return -1;
};
};

template <template<bool T> class child_t, bool is_desc, int value>
class Add
{

child_t<is_desc> child;
int func
{
if(is_desc)
return value + child.func;
return -(value + child.func;
};
};

template <template<bool T> class child_t, bool is_desc, int value>
class Mult
{

child_t<is_desc> child;
int func
{
if(is_desc)
return value + child.func;
return -(value + child.func;
};
};

template<template<bool B> class type_t>
class Storage
{
type_t<true> one;
type_t<false> two;
};

template <bool b>
typedef Unit<b> class Container;

template <bool b>
typedef Add<Unit, b, 15> class Container2;

template <bool b>
typedef Mult<Add<Unit, b, 15>, b, 4> class Container3;

int main
{
Storage<Container> a;
printf("res: %d\n", a.func;
return 0;
}


в typedef'aх я глупость написал, но что-то такое хочу получить.

smit1

в typedef'aх я глупость написал, но что-то такое хочу получить
В C++11 тайпдефы с параметрами есть (называются alias templates вот только далеко не все компиляторы их умеют.

Dasar

иногда помогает следующий workaround (но появляется чехарда с одинаковыми, но не совпадающими типами)

template <bool B>
class Container:public Unit<B>{};

template <bool B>
class Container2:public Add<Unit, B, 15>{};

template <bool B>
class Container3: public Mult<Container2, B, 4>{};

Phoenix

какой грязный хак, но мне походу подойдёт.
Спасибище!
 
 $ cat main.cpp 
#include <stdio.h>

template<bool is_desc>
class Unit
{
public:
int func
{
if(is_desc) return 1;
return -1;
};
};

template <class child_t, bool is_desc, int value>
class Add
{
public:

child_t child;
int func
{
if(is_desc)
return value + child.func;
return -(value + child.func;
};
};

template <class child_t, bool is_desc, int value>
class Mult
{
public:

child_t child;
int func
{
if(is_desc)
return value + child.func;
return -(value + child.func;
};
};

template<template<bool B> class type_t>
class Storage
{
public:
type_t<true> one;
type_t<false> two;
void pprintf
{
printf("1: %d\n", one.func;
printf("2: %d\n", two.func;
};
};

template <bool b>
class Container : public Unit<b>{};

template <bool b>
class Container2 : public Add<Unit<b>, b, 15>{};

template <bool b>
class Container3 : public Mult<Add<Unit<b>, b, 15>, b ,4>{};


int main
{
Storage<Container> a;
Storage<Container2> a2;
Storage<Container3> a3;
a.pprintf;
a2.pprintf;
a3.pprintf;
return 0;
}

$ g++ main.cpp

$./a.out
1: 1
2: -1
1: 16
2: -14
1: 20
2: 10

smit1

иногда помогает следующий workaround (но появляется чехарда с одинаковыми, но не совпадающими типами)
Обычно в таких случаях делают как-то так:
template<template<bool B> class type_t>
class Storage
{
public:

typename type_t<true>::type one;
typename type_t<false>::type two;

void pprintf
{
printf("1: %d\n", one.func;
printf("2: %d\n", two.func;
};
};

template <bool b>
struct Container { typedef Unit<b> type; };

template <bool b>
struct Container2 { typedef Add<Unit<b>, b, 15> type; };

template <bool b>
struct Container3 { typedef Mult<Add<Unit<b>, b, 15>, b, 4> type; };

Storage<Container> a;
Storage<Container2> a2;
Storage<Container3> a3;

А вообще, не удивлюсь, если в свежем gcc уже alias templates есть.
Оставить комментарий
Имя или ник:
Комментарий: