Loki Typelists

J

Jon Slaughter

I'm having some issues using loki's typelists and I'm wondering if there is
something I'm missing.

I'm trying to create a template who's specialization sorta looks like

template <int I, class T>
struct Node
{
enum {Index = I};
typedef T Class;
};

typedef Node<0, NullClass> NullNode;


template <int I, class T1, class T2>
struct T<I, Typelist<T1, T2> >
: TL::TypeAtNonStrict<Typelist<T1,T2>, TL::IndexOf<Typelist<T1, T2>,
Node<I,*> >::value>, NullNode>::Result::Class
{
.....


the problem is at Node<I,*>, the idea is to search through the Typelist for
the Node that has index corresponding to I and return the class for that
node... the problem is I have to specify *. I've tried to add a
parameterization T3 to the template and replace * with T3 but then it says
T3 is not used. If I specify * to some class then ofcourse it won't work
because it will only match instances in the Typelist that will have that
class too...

Is there any way to do this by getting the template to parameterize * so
that I can only match the Index?

I feel that I will end up having to modify the IndexOf algorithm to work
specifically with Node to compare only the Index value and just pass * a
dummy variable like NullNode that will be ignored. Just wondering if there
is a better way?

Thanks,
Jon
 
G

Greg

Jon said:
I'm having some issues using loki's typelists and I'm wondering if there is
something I'm missing.

I'm trying to create a template who's specialization sorta looks like

template <int I, class T>
struct Node
{
enum {Index = I};
typedef T Class;
};

typedef Node<0, NullClass> NullNode;


template <int I, class T1, class T2>
struct T<I, Typelist<T1, T2> >
: TL::TypeAtNonStrict<Typelist<T1,T2>, TL::IndexOf<Typelist<T1, T2>,
Node<I,*> >::value>, NullNode>::Result::Class
{
....


the problem is at Node<I,*>, the idea is to search through the Typelist for
the Node that has index corresponding to I and return the class for that
node... the problem is I have to specify *. I've tried to add a
parameterization T3 to the template and replace * with T3 but then it says
T3 is not used. If I specify * to some class then ofcourse it won't work
because it will only match instances in the Typelist that will have that
class too...

Is there any way to do this by getting the template to parameterize * so
that I can only match the Index?

I feel that I will end up having to modify the IndexOf algorithm to work
specifically with Node to compare only the Index value and just pass * a
dummy variable like NullNode that will be ignored. Just wondering if there
is a better way?

Thanks,
Jon

Why not use tuples instead? the tuple_element<int, tuple> template
returns the type at a particular index of a tuple:

...
#include <tr1/tuple>
using std::tr1::tuple;
using std::tr1::tuple_element;

typedef tuple<int, char, long*, void(*)(int)> Tuple;

tuple_element<2, Tuple>::type; // 3rd type in Tuple (long*)

Greg
 
J

Jon Slaughter

Why not use tuples instead? the tuple_element<int, tuple> template
returns the type at a particular index of a tuple:

...
#include <tr1/tuple>
using std::tr1::tuple;
using std::tr1::tuple_element;

typedef tuple<int, char, long*, void(*)(int)> Tuple;

tuple_element<2, Tuple>::type; // 3rd type in Tuple (long*)

Greg

Cause I'm not trying to find the ith element in the type. I'm trying to find
the index of some type... the opposite of what you are doing. The problem is
that the IndexOf template in loki compares the whole object while I only
want to compare half of it.

Basicaly I have a list of Nodes. A node contains an *Index* and a class
type. By using IndexOf I can easily find the index of some "exact" node but
I cannot use it to just find the index of of some Node that has a matching
*Index* value.

i.e. (pseudo code)

List = {Node<1, MyClass>, Node<4, YourClass>, Node<54, SomeClass>}

IndexOf(List, Node<4,YourClass>} will return 1 because it is the second
entry in the list...

But I only want to find the index of ANY class that has an *Index* of 4, so


IndexOf(List, Node<1, Yourclass>) will fail, but I want it to return 0
because the Indecies MATCH!

so in some sense I want to do

IndexOf(List, Node<54, *>) should return 2.

where * can be anything.

i.e., I want to do the search over the a member type in the type itself
instead of over the whole type. This is proving to be pretty hard to do
though(for me anyways) ;/ I'm trying to modify the IndexOf algorithm to
basicaly do something like this:

ClassAt(List, 0) == MyClass
ClassAt(List, 1) == YourClass
ClassAt(List, 2) == SomeClass

Sort of a map container but using templates. I didn't know that std had a
similar type container so I might switch to it instead of using Loki if I
can get away with it. I think I will only need it in one part of my code so
I don't want to have to include some non-standard library stuff(if the type
stuff is standard) if I don't have too.

Thanks,
Jon
 
J

Jon Slaughter

Jon Slaughter said:
Cause I'm not trying to find the ith element in the type. I'm trying to
find the index of some type... the opposite of what you are doing. The
problem is that the IndexOf template in loki compares the whole object
while I only want to compare half of it.

Basicaly I have a list of Nodes. A node contains an *Index* and a class
type. By using IndexOf I can easily find the index of some "exact" node
but I cannot use it to just find the index of of some Node that has a
matching *Index* value.

i.e. (pseudo code)

List = {Node<1, MyClass>, Node<4, YourClass>, Node<54, SomeClass>}

IndexOf(List, Node<4,YourClass>} will return 1 because it is the second
entry in the list...

But I only want to find the index of ANY class that has an *Index* of 4,
so


IndexOf(List, Node<1, Yourclass>) will fail, but I want it to return 0
because the Indecies MATCH!

so in some sense I want to do

IndexOf(List, Node<54, *>) should return 2.

where * can be anything.

i.e., I want to do the search over the a member type in the type itself
instead of over the whole type. This is proving to be pretty hard to do
though(for me anyways) ;/ I'm trying to modify the IndexOf algorithm to
basicaly do something like this:

ClassAt(List, 0) == MyClass
ClassAt(List, 1) == YourClass
ClassAt(List, 2) == SomeClass

Sort of a map container but using templates. I didn't know that std had a
similar type container so I might switch to it instead of using Loki if I
can get away with it. I think I will only need it in one part of my code
so I don't want to have to include some non-standard library stuff(if the
type stuff is standard) if I don't have too.

Thanks,
Jon

Ofcourse it would be nice if one could make this procedure more general.
i.e., if one could extract the index of a type from a list that matches a
designated type only partially(and you get to choose what parts of the type
should match).

Jon
 
J

Jon Slaughter

I managed to hack the TypeAt code to get what I wanted but I am not at all
sure it is good code. It seems to work but only cause I spend about an hour
hacking the code trying to get something to work.

template <int i, class T>
struct Node
{
enum {Index = i };
typedef T Class;
};

struct NullClass { void Null() { } };
typedef Node<-1, NullClass> NullNode;

template <class TList, unsigned int index>
class NodeWithLoc
{
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;

private:

//ASSERT_TYPELIST(TList);
template<unsigned int i>

struct In
{
typedef typename NodeWithLoc<Tail, index>::Result Result;
};

template <>
struct In<-1>
{
typedef typename NullNode Result;
};

template <>
struct In<Head::Index>
{
typedef typename Head Result;
};

public:
typedef typename In<index>::Result Result;
};

template<unsigned int I> struct NodeWithLoc<NullType, I>
{
typedef NullNode Result;
};



-----------

Hopefully someone can understand a lot better on whats going on and see if
there are any logic problems or potential errors. I'm really fuzzy on these
recursive aspects of templates and it gets confusing because it seems that
the "standard" programming logic isn't the same. (i.e., if statements are
done by template specialization, iteration by recursion, etc...)



Anyways, basicaly what this does/is suppose to do is say I have

typedef TYPELIST_3<Node1, Node2, Node3> Nodes;

then

NodeAtLoc<Nodes, 2>::Result returns the Node object that has a loc(i.e.
index in this case) of 2.

if we have

typedef Node<2, SomeClass> Node3;

then the above will be Node3.

which is exactly what I want I hope ;/ Things are getting fuzzy ;/ Maybe
things will make more sense tomarrow.

Jon
 
J

Jon Slaughter

Heh, ok, here is some revised code that works for "2D" tree's. I'm wondering
if this process can be generalised for "nD" tree's?

I've included some sample code to play around with it.


#include <iostream>
#include <string>
using namespace std;

#include <Loki/TypeList.h>




template <int x, int y, class T>
struct Node
{
enum {X = x, Y = y };
typedef T Class;
};

struct NullClass { };
typedef Node<-1, -1, NullClass> NullNode;


// Recursively checks the nodes in the NodeList for having location (X,Y) =
(i,j).
// Returns the Type with that location in Result.
template <class NodeList, int i, int j> class NodeWithLoc
{
typedef typename NodeList::Head Head;
typedef typename NodeList::Tail Tail;
private:
//ASSERT_TYPELIST(TList);

// Performs the rescurisve process on the NodeList
template<int i, int j> struct In { typedef typename NodeWithLoc<Tail, i,
j>::Result Result; };

// Specializes incase of end of Typelist returning NullNode because of
no match
template <int j> struct In<-1, j> { typedef typename NullNode Result; };

// Specializes incase of end of Typelist returning NullNode because of
no match
template <int i> struct In<i, -1> { typedef typename NullNode Result; };

// Matches current node in recursive process to the location we want
template <> struct In<Head::X, Head::Y> { typedef typename Head
Result; };

public:
// Performs the recursive process checking
typedef typename In<i, j>::Result Result;
};

// Specializes the end of the NodeList to return a NullNode(i.e., Node with
location (i,j) not found)
template<int i, int j> struct NodeWithLoc<Loki::NullType, i, j> { typedef
NullNode Result; };


/////////////////////////////////////////////////////


struct MyClass { void MyFunc() { cout << "MyFunc()\n"; } };
struct MyEndClassLeft { void MyEndLeft() { cout << "MyEndLeft()\n"; } };
struct MyEndClassRight { void MyEndRight() { cout << "MyEndRight()\n"; } };

int main( int argc, char* argv[] )
{

typedef Node<1, 4, MyClass> C1;
typedef Node<2, 1, MyEndClassRight> C2;
typedef Node<3, 33, MyEndClassLeft> C3;
typedef Node<14, 153, NullClass> C4;
typedef TYPELIST_4(C2,C1,C4,C3) Q;

// Finds the Node in Q with location 3,33 and returns that Node
int x = NodeWithLoc<Q, 3, 33>::Result::X;
int y = NodeWithLoc<Q, 3, 33>::Result::Y;

cout << "(" << x << ", " << y << ")" << endl;


// prints "MyEndRight()"
NodeWithLoc<Q, 2, 1>::Result::Class S;
S.MyEndRight();

// prints "MyFunc()"
NodeWithLoc<Q, 1, 4>::Result::Class S;
S.MyFunc();


cout << endl;
system("PAUSE");
return 0;
}


Seems like one could use a similar idea to simplify certain compile time
condition compliations.

i.e.

Say several Node::Class'es implemented a function called "print"

then one could do

typedef TYPELIST_4<N1,N2,N3,N4> Q;
NodeWithLoc<Q, I>::Result::Class S;

S.print();


depending on what I is one would be able to "choose" between several
different prints. Though I think something like this is already done but
this seems like it might make things pretty simple in certain situations.

Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top