хорошо, я использую ваши Контейнерные структуры, объединяю их с XCont и определяю XContainer, который вы хотите:
// a (bit-)LIST is an int that contains the value (TAIL<<1|HEAD),
// where TAIL is a LIST, and HEAD is either 1 or 0.
// while iterating through the LIST from right,
// SHL counts how far each consumed HEAD has to be shifted left,
// back to its original position.
template<int TAIL,int HEAD,int SHL>
struct XCont;
//the empty LIST
template<int SHL>
struct XCont<0,0,SHL>{};
//HEAD equals 0, so we just recurse through the TAIL.
template<int TAIL,int SHL>
struct XCont<TAIL,0,SHL>:public XCont< (TAIL>>1) , (TAIL&1) , (SHL+1) >{};
//HEAD equals 1, so we do like above, but we have to append Container< (1<<SHL) >.
template<int TAIL,int SHL>
struct XCont<TAIL,1,SHL>:public XCont< (TAIL>>1) , (TAIL&1) , (SHL+1) >,public Container< (1<<SHL) >{};
template<int E>
struct XContainer:public XCont< (E>>1) , (E&1) , (0) >{};
Работает так:
- Битовая маска будет интерпретироваться как СПИСОК битов справа налево (сначала младший бит).
- Мы перебираем биты, сдвигая биты (>>) LIST.
- СПИСОК представлен в стиле функционального программирования в виде кортежа HEAD и TAIL, где HEAD - это первый элемент, а TAIL - это список оставшихся элементов без этого HEAD.
- Всякий раз, когда мы находим 1-бит в качестве HEAD, мы хотим пересчитать его битовую позицию, поэтому мы считаем это с помощью SHL. Конечно, есть и другие подходы, такие как битовое смещение маски над списком и проверка ее значения на 0 и не на 0.
Они равны:
- XContainer
- XContainer <0x04 | 0x02 | 0x01>
- XContainer <0x07>
- XCont <(0x07 >> 1), (0x07 & 1), (0)>
- XCont <((EBOOL | EFLOAT | EINT) >> 1), (EINT), (0)>
- XCont <((EBOOL | EFLOAT) >> 1), (EINT), (0)>
- XCont <((EBOOL | EFLOAT) >> 1), (EINT >> 0), (0)>
- XCont , где ...
- TAIL = ((EBOOL | EFLOAT) >> 1)
- 1 = (EINT >> 0)
- SHL = (0)
- EINT = (1 << SHL) </em>
- XCont > 1, TAIL & 1, SHL + 1> ++ Контейнер <(1 << SHL)>
- ...
- XCont <0,0, (3)> ++ контейнер <(1 << (2))> ++ контейнер <(1 << (1))> ++ контейнер <(1 << (0) )>
- XCont <0,0, (3)> ++ контейнер ++ контейнер ++ контейнер
Шаблоны C ++ ведут себя как сопоставление с образцом в Haskell.
Поэтому мне проще думать об этом в простом стиле функций Haskell без каких-либо причудливых вещей в Haskell. Если кому-то интересно:
xcontainer :: Int -> String
xcontainer(e) = "struct XContainer:" ++ (
xcont( (e .>>. 1) , (e .&. 1) , (0) )
) ++ "{}"
xcont :: (Int,Int,Int) -> String
xcont( 0,0,shl) = "public XCont<0,0," ++ show(shl) ++ ">"
xcont(tail,0,shl) = ( xcont( (tail .>>. 1) , (tail .&. 1) , (shl+1) )
)
xcont(tail,1,shl) = ( xcont( (tail .>>. 1) , (tail .&. 1) , (shl+1) )
) ++ "," ++ container(1 .<<. shl)
container :: Int -> String
container(e) = "public Container<" ++ show(e) ++ ">"
(Это допустимый язык Haskell, но в стиле написания не на языке Haskell.)