Metaprogramming "for" loop

P

PengYu.UT

Hi,

I have the code below this email. I want to replace the last 4 lines
with a Metaprogramming loop to get something like the following (I
don't know the syntax). Is it possible?

for type in {left_tag, right_tag, down_tag, up_tag) {
fun(type());
}


Thanks,
Peng

struct left_tag{};
struct right_tag{};
struct down_tag{};
struct up_tag{};

template <typename Dir>
void fun(Dir) { }

//Can I replace the following code with a metaprogramming "for" loop
fun(left_tag());
fun(right_tag());
fun(down_tag());
fun(up_tag());
 
K

kwikius

Hi,

I have the code below this email. I want to replace the last 4 lines
with a Metaprogramming loop to get something like the following (I
don't know the syntax). Is it possible?

for type in {left_tag, right_tag, down_tag, up_tag) {
fun(type());

}

Thanks,
Peng

struct left_tag{};
struct right_tag{};
struct down_tag{};
struct up_tag{};

template <typename Dir>
void fun(Dir) { }

//Can I replace the following code with a metaprogramming "for" loop
fun(left_tag());
fun(right_tag());
fun(down_tag());
fun(up_tag());

Yes.

However in all the metaprogramming libraries I know of you need to
put the tags in some sort of tuple which is accessible to
metaprogramming. (std::tr1::tuple could be adapted for this but no std
way exists AFAIK) In my own libraries I would do something like the
following code below --->

Other libraries that do similar are boost::fusion (not released but
accessible via CVS). I think you can do similar with boost::mpl though
it is nominally only for compile time programming AFAIK and isnt
compatible with std::tr1 type_traits or std::tr1::tuple IIRC.

#include <quan/fun/vector4.hpp>
#include <quan/fun/for_each.hpp>

struct left_tag{};
struct right_tag{};
struct down_tag{};
struct up_tag{};

// some tuple with metaprogramming facilities
typedef quan::fun::vector4<left_tag,right_tag,down_tag,up_tag> tags;

// any functor with similar signature will do.

struct fun{

template <typename T>
void operator()(T const & t) const
{
std::cout << typeid(T).name() <<'\n';
}

};
int main()
{
quan::fun::for_each(tags(),fun());

}

/*
output:

struct left_tag
struct right_tag
struct down_tag
struct up_tag

*/
 
P

Piyo

Hi,

I have the code below this email. I want to replace the last 4 lines
with a Metaprogramming loop to get something like the following (I
don't know the syntax). Is it possible?

for type in {left_tag, right_tag, down_tag, up_tag) {
fun(type());
}


Thanks,
Peng

struct left_tag{};
struct right_tag{};
struct down_tag{};
struct up_tag{};

template <typename Dir>
void fun(Dir) { }

//Can I replace the following code with a metaprogramming "for" loop
fun(left_tag());
fun(right_tag());
fun(down_tag());
fun(up_tag());

I am quoting one of my previous posts that may be helpful to you
regarding this. The idea is it define a tuple that has all your
structures in one place and let the template metaprogram unfold it
for you.

So in your case, you will need to define
typedef boost::tuple<left_tag,right_tag,down_tag,up_tag> stuffToProc;

then you do stuff similar to the metaprogram. Here I modified it to
call your function, fun()

// recursive case
template< int N >
class test
{
public:
static void doIt( const stuffToProc &t )
{
test<N-1>::doIt( t );
fun( t.get<N>() );
}
};

// basis case
template<>
class test<0>
{
public:
static void doIt( const stuffToProc &t )
{
fun( t.get<0>() );
}
};

then you can use it as follows:

int
main()
{
stuffToProc thisIsTheStuff;
test<4>::doit( thisIsTheStuff );
}

I was investigating a way to manufacture objects based
on an array of typeid's but I did not have the time.
I think that the problem you are describing can be
solved differently and probably easily if we can figure
out an efficient way to create arbitrary typed objects
from its typeid. When I get the chance, I'll investigate
this further since this problem keeps popping up now and
again.

HTH
 
K

kwikius

<...>

Thats basically it using boost::tuple..
You can wrap the implementation in some for_each construct, which
automatically computes the size and use more template params. For
boost tuple you can get the size by tuple::length, and dont forget its
zero based so off by 1.
It should then work for different element_types and tuple lengths
too...

regards Andy Little

#include <boost/tuple/tuple.hpp>
#include <iostream>

struct left_tag{};
struct right_tag{};
struct down_tag{};
struct up_tag{};

typedef boost::tuple<left_tag,right_tag,down_tag,up_tag> stuffToProc;

struct fun{

template <typename T>
void operator()(T const & t)const
{
std::cout << typeid(T).name() <<'\n';
}
};



template< int N >
class test {
public:
template <typename T, typename F>
static void doIt( const T &t,F f )
{
test<N-1>::doIt( t ,f );
f( t. template get<N>() );
}
};

// basis case
template<>
class test<0> {
public:
template <typename T, typename F>
static void doIt( const T &t, F f )
{
f( t. template get<0>() );
}
};

// some for_each
template <typename T, typename F>
void for_each( T & t, F f)
{
test<(boost::tuples::length<T>::value -1)>::doIt(t,f);
}


int main()
{
stuffToProc thisIsTheStuff;
for_each(thisIsTheStuff ,fun());
}

regards
Andy Little
 
K

kwikius

<...>

Thats basically it using boost::tuple..
You can wrap the implementation in some for_each construct, which
automatically computes the size and use more template params. For
boost tuple you can get the size by tuple::length, and dont forget its
zero based so off by 1.
It should then work for different element_types and tuple lengths
too...

regards Andy Little

Oh and you can use the make_tuple function so you dont need the
explicit typedef, which is pretty close to what you want I think :

int main()
{
// stuffToProc thisIsTheStuff;
for_each(
boost::tuples::make_tuple(
left_tag(),right_tag(),up_tag(),down_tag()
)
,fun());

// or ...
left_tag lt;
right_tag rt;
down_tag dt;
up_tag ut;

using boost::tuples::make_tuple;

for_each(make_tuple(lt,rt,ut,dt),fun());


regards
Andy Little
 
P

Piyo

kwikius said:
int main()
{
// stuffToProc thisIsTheStuff;
for_each(
boost::tuples::make_tuple(
left_tag(),right_tag(),up_tag(),down_tag()
)
,fun());

// or ...
left_tag lt;
right_tag rt;
down_tag dt;
up_tag ut;

using boost::tuples::make_tuple;

for_each(make_tuple(lt,rt,ut,dt),fun());


regards
Andy Little
Pretty sweet stuff there Andy :) I was also thinking to
suggest dropping the class and make "test" into a function
template. I wrote that original code to solve something
else but eventually didn't (I couldn't figure out some
stuff).

On a different note: you brought up the use of tr1 data
structs. Do you know of a website detailing the stuff there?
I can't seem to find one that is as clean and organized
as sgi's website of the STL stuff.

Thanks!
 
J

Jerry Coffin

[ ... ]
On a different note: you brought up the use of tr1 data
structs. Do you know of a website detailing the stuff there?
I can't seem to find one that is as clean and organized
as sgi's website of the STL stuff.

I don't know of a web site, but Pete Becker's book (_The C++ Standard
Library Extensions_) is quite good.
 
K

kwikius

[ ... ]
On a different note: you brought up the use of tr1 data
structs. Do you know of a website detailing the stuff there?
I can't seem to find one that is as clean and organized
as sgi's website of the STL stuff.

I don't know of a web site, but Pete Becker's book (_The C++ Standard
Library Extensions_) is quite good.

Yes, and you can find out the specs by looking at the draft C++
extensions paper:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf


regards
Andy Little
 
P

PengYu.UT

Yes.

However in all the metaprogramming libraries I know of you need to
put the tags in some sort of tuple which is accessible to
metaprogramming. (std::tr1::tuple could be adapted for this but no std
way exists AFAIK) In my own libraries I would do something like the
following code below --->

Other libraries that do similar are boost::fusion (not released but
accessible via CVS). I think you can do similar with boost::mpl though
it is nominally only for compile time programming AFAIK and isnt
compatible with std::tr1 type_traits or std::tr1::tuple IIRC.

#include <quan/fun/vector4.hpp>
#include <quan/fun/for_each.hpp>

struct left_tag{};
struct right_tag{};
struct down_tag{};
struct up_tag{};

// some tuple with metaprogramming facilities
typedef quan::fun::vector4<left_tag,right_tag,down_tag,up_tag> tags;

// any functor with similar signature will do.

struct fun{

template <typename T>
void operator()(T const & t) const
{
std::cout << typeid(T).name() <<'\n';
}

};

int main()
{
quan::fun::for_each(tags(),fun());

}

/*
output:

struct left_tag
struct right_tag
struct down_tag
struct up_tag

*/

Could you please show me what are in the files quan/fun/vector4.hpp
quan/fun/for_each.hpp?

Thanks,
Peng
 
P

PengYu.UT

[ ... ]
On a different note: you brought up the use of tr1 data
structs. Do you know of a website detailing the stuff there?
I can't seem to find one that is as clean and organized
as sgi's website of the STL stuff.
I don't know of a web site, but Pete Becker's book (_The C++ Standard
Library Extensions_) is quite good.

Yes, and you can find out the specs by looking at the draft C++
extensions paper:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf

regards
Andy Little

Are these implemented in any compiler, yet?

Tahnks,
Peng
 

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

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,188
Latest member
Crypto TaxSoftware

Latest Threads

Top