By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,364 Members | 2,348 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,364 IT Pros & Developers. It's quick & easy.

Metaprogramming question

P: n/a
I want to define a bunch of class like the following.
In general, test<n> have n integer arguments. It has a member function
"doit", which returns

l_i for 0 <= i < l
0 for i == l or 2l + 1
-l_(2n - i) for l+1 <= i < 2l

I'm wondering how to define these test* classes using metaprogramming?
Would you please let me know, if you have any ideas.

Thanks,
Peng

#include <vector>
#include <cassert>
#include <iostream>

class test1{
public:
test1(int l0){
_v.push_back(l0);
}
int doit(int i){
switch(i){
case 0:
return _v[0];
case 1:
return 0;
case 2:
return -_v[0];
case 3:
return 0;
default:
assert(0);
}
}
private:
std::vector<int> _v;
};

class test2{
public:
test2(int l0, int l1){
_v.push_back(l0);
_v.push_back(l1);
}
int doit(int i){
switch(i){
case 0:
return _v[0];
case 1:
return _v[1];
case 2:
return 0;
case 3:
return -_v[1];
case 4:
return -_v[0];
case 5:
return 0;
default:
assert(0);
}
}
private:
std::vector<int> _v;
};

int main(int argc, char *argv[]) {
test1 t1(1);
for(int i = 0; i < 2 * 1 + 2; ++ i){
std::cout << t1.doit(i) << std::endl;
}
test2 t2(1,2);
for(int i = 0; i < 2 * 2 + 2; ++ i){
std::cout << t2.doit(i) << std::endl;
}
}

Oct 24 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a

<Pe*******@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
I want to define a bunch of class like the following.
In general, test<n> have n integer arguments. It has a member function
"doit", which returns

l_i for 0 <= i < l
0 for i == l or 2l + 1
-l_(2n - i) for l+1 <= i < 2l

I'm wondering how to define these test* classes using metaprogramming?
Would you please let me know, if you have any ideas.

Thanks,
Peng

#include <vector>
#include <cassert>
#include <iostream>

class test1{
public:
test1(int l0){
_v.push_back(l0);
}
int doit(int i){
switch(i){
case 0:
return _v[0];
case 1:
return 0;
case 2:
return -_v[0];
case 3:
return 0;
default:
assert(0);
}
}
private:
std::vector<int> _v;
};

class test2{
public:
test2(int l0, int l1){
_v.push_back(l0);
_v.push_back(l1);
}
int doit(int i){
switch(i){
case 0:
return _v[0];
case 1:
return _v[1];
case 2:
return 0;
case 3:
return -_v[1];
case 4:
return -_v[0];
case 5:
return 0;
default:
assert(0);
}
}
private:
std::vector<int> _v;
};

int main(int argc, char *argv[]) {
test1 t1(1);
for(int i = 0; i < 2 * 1 + 2; ++ i){
std::cout << t1.doit(i) << std::endl;
}
test2 t2(1,2);
for(int i = 0; i < 2 * 2 + 2; ++ i){
std::cout << t2.doit(i) << std::endl;
}
}


Could you do something like:

template<unsigned int N>
class Test : public Test<N-1>
{
public:
Test<N>( );
Test<N>(int n1)
Test<N>(int n1, int n2)
Test<N>(int n1, int n2, int n3)
etc .
int doit( int n )
{
// some formula...to compute the value....
}
vector<int> _args;

};

// specialization to end the defintion chain.
template<>
class Test<0>
{
int doit( int n );

};
Test<N>(int n1 )
:Test<N-1>( )
{
_args.push_back(n1);
}

Test<N>(int n1 , int n2)
:Test<N-1>(n2)
{
_args.push_back(n2);

}

Test<N>(int n1 , int n2, int n3)
:Test<N-1>(n2,n3 )
{
_args.push_back(n3);

}

As far as I know, there isn't a way to parameterize the number of arguments
for the
template member functions - although there might be something in boost you
could
use. If you have a fairly bounded number for N, you can just enumerate all
possibilities
by including constructors for Test<N> with 0 through N arguments.


Oct 24 '05 #2

P: n/a
Pe*******@gmail.com wrote:
I want to define a bunch of class like the following.
In general, test<n> have n integer arguments. It has a member function
"doit", which returns

l_i for 0 <= i < l
0 for i == l or 2l + 1
-l_(2n - i) for l+1 <= i < 2l

I'm wondering how to define these test* classes using metaprogramming?
Would you please let me know, if you have any ideas.

Thanks,
Peng

#include <vector>
#include <cassert>
#include <iostream>

class test1{
public:
test1(int l0){
_v.push_back(l0);
}
int doit(int i){
switch(i){
case 0:
return _v[0];
case 1:
return 0;
case 2:
return -_v[0];
case 3:
return 0;
default:
assert(0);
}
}
private:
std::vector<int> _v;
};

class test2{
public:
test2(int l0, int l1){
_v.push_back(l0);
_v.push_back(l1);
}
int doit(int i){
switch(i){
case 0:
return _v[0];
case 1:
return _v[1];
case 2:
return 0;
case 3:
return -_v[1];
case 4:
return -_v[0];
case 5:
return 0;
default:
assert(0);
}
}
private:
std::vector<int> _v;
};

int main(int argc, char *argv[]) {
test1 t1(1);
for(int i = 0; i < 2 * 1 + 2; ++ i){
std::cout << t1.doit(i) << std::endl;
}
test2 t2(1,2);
for(int i = 0; i < 2 * 2 + 2; ++ i){
std::cout << t2.doit(i) << std::endl;
}
}


First, please avoid using the lowercase "L" as a variable name or to
differentiate variable names. It's quite confusing to separate 10 from
the l0 for instance. Also I had trouble with these formulas:

-l_(2n - i)
l_i

But based on the program provided I think I figured it out. Anyway, the
following program should be enough to get you started:

template<int N>
struct Integer
{
static const int value = N;
typedef Integer<N+1> next;
};

template <class N, class C >
struct Test
{
static const int value = C::value < N::value ?
C::value :
-1-(2*N::value - C::value);
};

// Integer class is needed for this specialization:
template <int N>
struct Test< Integer<N>, Integer<2*N+1> >
{
static const int value = 0;
};

template <class N>
struct Test<N, N>
{
static const int value = 0;
};

template <class N, class C>
void DoIt( const Test<N, C> )
{
std::cout << Test<N, C>::value << " ";

DoIt( Test<N, typename C::next >() );
}

template <int N>
void DoIt( const Test<Integer<N>, Integer<N*2+1> > )
{
std::cout << Test<Integer<N>, Integer<N*2+1> >::value << " ";
}

int main()
{
DoIt( Test< Integer<1>, Integer<0> >());
std::cout << std::endl;
DoIt( Test< Integer<2>, Integer<0> >());
std::cout << std::endl;
}

Output:
0 0 -1 0
0 1 0 -2 -1 0

Greg

Oct 24 '05 #3

P: n/a

Greg wrote:
Pe*******@gmail.com wrote:
I want to define a bunch of class like the following.
In general, test<n> have n integer arguments. It has a member function
"doit", which returns

l_i for 0 <= i < l
0 for i == l or 2l + 1
-l_(2n - i) for l+1 <= i < 2l

I'm wondering how to define these test* classes using metaprogramming?
Would you please let me know, if you have any ideas.

Thanks,
Peng
.... First, please avoid using the lowercase "L" as a variable name or to
differentiate variable names. It's quite confusing to separate 10 from
the l0 for instance. Also I had trouble with these formulas:

-l_(2n - i)
l_i

But based on the program provided I think I figured it out. Anyway, the
following program should be enough to get you started:

template<int N>
struct Integer
{
static const int value = N;
typedef Integer<N+1> next;
};

template <class N, class C >
struct Test
{
static const int value = C::value < N::value ?
C::value :
-1-(2*N::value - C::value);
};
.... int main()
{
DoIt( Test< Integer<1>, Integer<0> >());
std::cout << std::endl;
DoIt( Test< Integer<2>, Integer<0> >());
std::cout << std::endl;
}

Output:
0 0 -1 0
0 1 0 -2 -1 0

Greg


Of course as soon as I post my program I notice an error. Change:

static const int value = C::value < N::value ?
C::value :
-1-(2*N::value - C::value);

to:

static const int value = C::value < N::value ?
C::value + 1:
-1-(2*N::value - C::value);

for the output:

1 0 -1 0
1 2 0 -2 -1 0

which at least matches the original program's output.

Greg

Oct 24 '05 #4

P: n/a

Dave Townsend wrote:
<Pe*******@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
I want to define a bunch of class like the following.
In general, test<n> have n integer arguments. It has a member function
"doit", which returns

l_i for 0 <= i < l
0 for i == l or 2l + 1
-l_(2n - i) for l+1 <= i < 2l

I'm wondering how to define these test* classes using metaprogramming?
Would you please let me know, if you have any ideas.

Thanks,
Peng

#include <vector>
#include <cassert>
#include <iostream>

class test1{
public:
test1(int l0){
_v.push_back(l0);
}
int doit(int i){
switch(i){
case 0:
return _v[0];
case 1:
return 0;
case 2:
return -_v[0];
case 3:
return 0;
default:
assert(0);
}
}
private:
std::vector<int> _v;
};

class test2{
public:
test2(int l0, int l1){
_v.push_back(l0);
_v.push_back(l1);
}
int doit(int i){
switch(i){
case 0:
return _v[0];
case 1:
return _v[1];
case 2:
return 0;
case 3:
return -_v[1];
case 4:
return -_v[0];
case 5:
return 0;
default:
assert(0);
}
}
private:
std::vector<int> _v;
};

int main(int argc, char *argv[]) {
test1 t1(1);
for(int i = 0; i < 2 * 1 + 2; ++ i){
std::cout << t1.doit(i) << std::endl;
}
test2 t2(1,2);
for(int i = 0; i < 2 * 2 + 2; ++ i){
std::cout << t2.doit(i) << std::endl;
}
}
With Metatemplates this may not be possible..to generate functions with
var args...
U can simply use a single template class with variable no. of args
passed to the constructor.
Could you do something like:

template<unsigned int N>
class Test : public Test<N-1>
{
public:
Test<N>( );
Test<N>(int n1)
Test<N>(int n1, int n2)
Test<N>(int n1, int n2, int n3)
etc .
int doit( int n )
{
// some formula...to compute the value....
}
vector<int> _args;

};

// specialization to end the defintion chain.
template<>
class Test<0>
{
int doit( int n );

};
Test<N>(int n1 )
:Test<N-1>( )
{
_args.push_back(n1);
}

Test<N>(int n1 , int n2)
:Test<N-1>(n2)
{
_args.push_back(n2);

}

Test<N>(int n1 , int n2, int n3)
:Test<N-1>(n2,n3 )
{
_args.push_back(n3);

}

As far as I know, there isn't a way to parameterize the number of arguments
for the
template member functions - although there might be something in boost you
could use. If you have a fairly bounded number for N, you can just enumerate all
possibilities
by including constructors for Test<N> with 0 through N arguments.


Oct 24 '05 #5

P: n/a

"Greg" <gr****@pacbell.net> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
Pe*******@gmail.com wrote:
<snip>
First, please avoid using the lowercase "L" as a variable name or to
differentiate variable names. It's quite confusing to separate 10 from
the l0 for instance. Also I had trouble with these formulas:


yessim massa

<snip>
Oct 24 '05 #6

P: n/a

"Dave Townsend" <da********@comcast.net> wrote in message
news:Rd********************@comcast.com...

<Pe*******@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com... <snip>
As far as I know, there isn't a way to parameterize the number of
arguments
for the
template member functions - although there might be something in boost you
could
use. If you have a fairly bounded number for N, you can just enumerate
all
possibilities
by including constructors for Test<N> with 0 through N arguments.


There is a preprocessor extension in boost that you can use to generate code
that is repeatative such as a series of "variable" parameters of some type.
I don't think this is a very efficient method though but it seems it will
get the job done.

http://www.boost.org/libs/preprocessor/doc/index.html

Jon

Oct 24 '05 #7

P: n/a

Jon Slaughter wrote:
"Greg" <gr****@pacbell.net> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
Pe*******@gmail.com wrote:


<snip>

First, please avoid using the lowercase "L" as a variable name or to
differentiate variable names. It's quite confusing to separate 10 from
the l0 for instance. Also I had trouble with these formulas:


yessim massa

<snip>


I guess you haven't realized that l's can look like 1's either. Oh
well, someday.
Greg

Oct 25 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.