Connecting Tech Pros Worldwide Help | Site Map

Templated array of templates specialized by array index

npankey@gmail.com
Guest
 
Posts: n/a
#1: Oct 11 '08
I've started experimenting with template metaprogramming in a small
project of mine. What I'm trying to accomplish is to generate a static
array of templated objects that get specialized based on there
position in the array. This should be possible but I can't figure out
exactly how to accomplish this.

The below code should better illustrate what I'm trying to do:

template <int I>
class Item
{
int X() { /*do default */ }
}

template <>
class Item<0>
{
int X() { /* do something special */ }
};

template <int N>
class Array
{
// The following obviously won't work
// How do I push this type of initialization to compile time???
Array()
{
for(int i=0; i<N; i++)
{
data[i] = Item<i>();
}
}

Item data[N];
}

int main()
{
Array<5items;
/* do stuff with items */
return 0;
}
Ian Collins
Guest
 
Posts: n/a
#2: Oct 11 '08

re: Templated array of templates specialized by array index


npankey@gmail.com wrote:
Quote:
I've started experimenting with template metaprogramming in a small
project of mine. What I'm trying to accomplish is to generate a static
array of templated objects that get specialized based on there
position in the array. This should be possible but I can't figure out
exactly how to accomplish this.
>
Not easily. Don't forget each specialisation of an Item is a unique
class, so you can have a array of different Items.

It you make Item polymorphic with a concrete base class and use an array
of base class pointers you might be able to make progress.

--
Ian Collins
Kai-Uwe Bux
Guest
 
Posts: n/a
#3: Oct 11 '08

re: Templated array of templates specialized by array index


npankey@gmail.com wrote:
Quote:
template <int I>
class Item
{
int X() { /*do default */ }
}
>
template <>
class Item<0>
{
int X() { /* do something special */ }
};
>
template <int N>
class Array
{
// The following obviously won't work
// How do I push this type of initialization to compile time???
Array()
{
for(int i=0; i<N; i++)
{
data[i] = Item<i>();
}
}
>
Item data[N];
}
>
int main()
{
Array<5items;
/* do stuff with items */
return 0;
}
Based on your code:

template <int I>
struct Item {

static
void put ( int* where ) {
Item<I-1>::put( where );
where[i] = Item<I>::X();
}

static
int X() {
return ( Item<I-1>::X() + Item<I-2>::X() );
}

};

template <>
struct Item<0{

static
void put ( int* where ) {
where[0] = Item<0>::X();
}

static
int X() {
return ( 1 );
}

};

template <>
struct Item<1{

static
void put ( int* where ) {
where[0] = Item<0>::X();
where[1] = Item<1>::X();
}

static
int X() {
return ( 1 );
}

};

template < int N >
struct Array {

Array() {
Item<N-1>::put( data );
}

int data[N];

};

#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>

int main()
{
Array<5items;
std::copy( items.data, items.data+5,
std::ostream_iterator<int>( std::cout, "\n" ) );
/* do stuff with items */
return 0;
}


Note, however, that the computation is not really done at compile time since
the static functions are executed at runtime. The following fixes at least
that:

template <int I>
struct Item {

static
void put ( int* where ) {
Item<I-1>::put( where );
where[i] = Item<I>::value;
}

static int const value =
Item<I-1>::value + Item<I-2>::value;

};

template <>
struct Item<0{

static
void put ( int* where ) {
where[0] = Item<0>::value;
}

static int const value = 1;

};

template <>
struct Item<1{

static
void put ( int* where ) {
where[0] = Item<0>::value;
where[1] = Item<1>::value;
}

static int const value = 1;

};

template < int N >
struct Array {

Array() {
Item<N-1>::put( data );
}

int data[N];

};

#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>

int main()
{
Array<5items;
std::copy( items.data, items.data+5,
std::ostream_iterator<int>( std::cout, "\n" ) );
/* do stuff with items */
return 0;
}


The array itself is populated at runtime in the constructor of Array. I
don't see a way to push that into compile time.


Best

Kai-Uwe Bux

npankey@gmail.com
Guest
 
Posts: n/a
#4: Oct 12 '08

re: Templated array of templates specialized by array index


On Oct 11, 3:20*pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
Quote:
npan...@gmail.com wrote:
Quote:
template <int I>
class Item
{
int X() { /*do default */ }
}
>
Quote:
template <>
class Item<0>
{
int X() { /* do something special */ }
};
>
Quote:
template <int N>
class Array
{
// The following obviously won't work
// How do I push this type of initialization to compile time???
Array()
{
for(int i=0; i<N; i++)
{
data[i] = Item<i>();
}
}
>
Quote:
Item data[N];
}
>
Quote:
int main()
{
Array<5items;
/* do stuff with items */
return 0;
}
>
Based on your code:
>
template <int I>
struct Item {
>
* static
* void put ( int* where ) {
* * Item<I-1>::put( where );
* * where[i] = Item<I>::X();
* }
>
* static
* int X() {
* * return ( Item<I-1>::X() + Item<I-2>::X() );
* }
>
};
>
template <>
struct Item<0{
>
* static
* void put ( int* where ) {
* * where[0] = Item<0>::X();
* }
>
* static
* int X() {
* * return ( 1 );
* }
>
};
>
template <>
struct Item<1{
>
* static
* void put ( int* where ) {
* * where[0] = Item<0>::X();
* * where[1] = Item<1>::X();
* }
>
* static
* int X() {
* * return ( 1 );
* }
>
};
>
template < int N >
struct Array {
>
* Array() {
* * Item<N-1>::put( data );
* }
>
* int data[N];
>
};
>
#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>
>
int main()
{
* * Array<5items;
* * std::copy( items.data, items.data+5,
* * * * * * * *std::ostream_iterator<int>( std::cout, "\n" ) );
* * /* do stuff with items */
* * return 0;
>
}
>
Note, however, that the computation is not really done at compile time since
the static functions are executed at runtime. The following fixes at least
that:
>
template <int I>
struct Item {
>
* static
* void put ( int* where ) {
* * Item<I-1>::put( where );
* * where[i] = Item<I>::value;
* }
>
* static int const value =
* * Item<I-1>::value + Item<I-2>::value;
>
};
>
template <>
struct Item<0{
>
* static
* void put ( int* where ) {
* * where[0] = Item<0>::value;
* }
>
* static int const value = 1;
>
};
>
template <>
struct Item<1{
>
* static
* void put ( int* where ) {
* * where[0] = Item<0>::value;
* * where[1] = Item<1>::value;
* }
>
* static int const value = 1;
>
};
>
template < int N >
struct Array {
>
* Array() {
* * Item<N-1>::put( data );
* }
>
* int data[N];
>
};
>
#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>
>
int main()
{
* * Array<5items;
* * std::copy( items.data, items.data+5,
* * * * * * * *std::ostream_iterator<int>( std::cout, "\n" ) );
* * /* do stuff with items */
* * return 0;
>
}
>
The array itself is populated at runtime in the constructor of Array. I
don't see a way to push that into compile time.
>
Best
>
Kai-Uwe Bux
Alright, so I'm getting a little closer and now I've at least got code
that compiles

struct Bar
{
int X() { return -1; }
};

template <int I>
struct Foo : Bar {};

template <>
struct Foo<0>
{
int X() { return 0; }
}

template <int N>
class Array
{
Bar data[N];
}

int main()
{
// Now I need to figure out how doing this ...
Array<3array1;

// ... can essentially result in this
Bar array2[3] = {Foo<0>(), Foo<1>(), Foo<2>()};
}
npankey@gmail.com
Guest
 
Posts: n/a
#5: Oct 12 '08

re: Templated array of templates specialized by array index


On Oct 11, 3:20*pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
Quote:
npan...@gmail.com wrote:
Quote:
template <int I>
class Item
{
int X() { /*do default */ }
}
>
Quote:
template <>
class Item<0>
{
int X() { /* do something special */ }
};
>
Quote:
template <int N>
class Array
{
// The following obviously won't work
// How do I push this type of initialization to compile time???
Array()
{
for(int i=0; i<N; i++)
{
data[i] = Item<i>();
}
}
>
Quote:
Item data[N];
}
>
Quote:
int main()
{
Array<5items;
/* do stuff with items */
return 0;
}
>
Based on your code:
>
template <int I>
struct Item {
>
* static
* void put ( int* where ) {
* * Item<I-1>::put( where );
* * where[i] = Item<I>::X();
* }
>
* static
* int X() {
* * return ( Item<I-1>::X() + Item<I-2>::X() );
* }
>
};
>
template <>
struct Item<0{
>
* static
* void put ( int* where ) {
* * where[0] = Item<0>::X();
* }
>
* static
* int X() {
* * return ( 1 );
* }
>
};
>
template <>
struct Item<1{
>
* static
* void put ( int* where ) {
* * where[0] = Item<0>::X();
* * where[1] = Item<1>::X();
* }
>
* static
* int X() {
* * return ( 1 );
* }
>
};
>
template < int N >
struct Array {
>
* Array() {
* * Item<N-1>::put( data );
* }
>
* int data[N];
>
};
>
#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>
>
int main()
{
* * Array<5items;
* * std::copy( items.data, items.data+5,
* * * * * * * *std::ostream_iterator<int>( std::cout, "\n" ) );
* * /* do stuff with items */
* * return 0;
>
}
>
Note, however, that the computation is not really done at compile time since
the static functions are executed at runtime. The following fixes at least
that:
>
template <int I>
struct Item {
>
* static
* void put ( int* where ) {
* * Item<I-1>::put( where );
* * where[i] = Item<I>::value;
* }
>
* static int const value =
* * Item<I-1>::value + Item<I-2>::value;
>
};
>
template <>
struct Item<0{
>
* static
* void put ( int* where ) {
* * where[0] = Item<0>::value;
* }
>
* static int const value = 1;
>
};
>
template <>
struct Item<1{
>
* static
* void put ( int* where ) {
* * where[0] = Item<0>::value;
* * where[1] = Item<1>::value;
* }
>
* static int const value = 1;
>
};
>
template < int N >
struct Array {
>
* Array() {
* * Item<N-1>::put( data );
* }
>
* int data[N];
>
};
>
#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>
>
int main()
{
* * Array<5items;
* * std::copy( items.data, items.data+5,
* * * * * * * *std::ostream_iterator<int>( std::cout, "\n" ) );
* * /* do stuff with items */
* * return 0;
>
}
>
The array itself is populated at runtime in the constructor of Array. I
don't see a way to push that into compile time.
>
Best
>
Kai-Uwe Bux
Alright, so I'm getting a little closer and now I've at least got code
that compiles

struct Bar
{
int X() { return -1; }
};

template <int I>
struct Foo : Bar {};

template <>
struct Foo<0>
{
int X() { return 0; }
}

template <int N>
class Array
{
Bar data[N];
}

int main()
{
// Now I need to figure out how doing this ...
Array<3array1;

// ... can essentially result in this
Bar array2[3] = {Foo<0>(), Foo<1>(), Foo<2>()};
}
npankey@gmail.com
Guest
 
Posts: n/a
#6: Oct 12 '08

re: Templated array of templates specialized by array index


On Oct 11, 4:41*pm, npan...@gmail.com wrote:
Quote:
On Oct 11, 3:20*pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
>
>
>
Quote:
npan...@gmail.com wrote:
Quote:
template <int I>
class Item
{
int X() { /*do default */ }
}
>
Quote:
Quote:
template <>
class Item<0>
{
int X() { /* do something special */ }
};
>
Quote:
Quote:
template <int N>
class Array
{
// The following obviously won't work
// How do I push this type of initialization to compile time???
Array()
{
for(int i=0; i<N; i++)
{
data[i] = Item<i>();
}
}
>
Quote:
Quote:
Item data[N];
}
>
Quote:
Quote:
int main()
{
Array<5items;
/* do stuff with items */
return 0;
}
>
Quote:
Based on your code:
>
Quote:
template <int I>
struct Item {
>
Quote:
* static
* void put ( int* where ) {
* * Item<I-1>::put( where );
* * where[i] = Item<I>::X();
* }
>
Quote:
* static
* int X() {
* * return ( Item<I-1>::X() + Item<I-2>::X() );
* }
>
Quote:
};
>
Quote:
template <>
struct Item<0{
>
Quote:
* static
* void put ( int* where ) {
* * where[0] = Item<0>::X();
* }
>
Quote:
* static
* int X() {
* * return ( 1 );
* }
>
Quote:
};
>
Quote:
template <>
struct Item<1{
>
Quote:
* static
* void put ( int* where ) {
* * where[0] = Item<0>::X();
* * where[1] = Item<1>::X();
* }
>
Quote:
* static
* int X() {
* * return ( 1 );
* }
>
Quote:
};
>
Quote:
template < int N >
struct Array {
>
Quote:
* Array() {
* * Item<N-1>::put( data );
* }
>
Quote:
* int data[N];
>
Quote:
};
>
Quote:
#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>
>
Quote:
int main()
{
* * Array<5items;
* * std::copy( items.data, items.data+5,
* * * * * * * *std::ostream_iterator<int>( std::cout, "\n" ) );
* * /* do stuff with items */
* * return 0;
>
Quote:
}
>
Quote:
Note, however, that the computation is not really done at compile time since
the static functions are executed at runtime. The following fixes at least
that:
>
Quote:
template <int I>
struct Item {
>
Quote:
* static
* void put ( int* where ) {
* * Item<I-1>::put( where );
* * where[i] = Item<I>::value;
* }
>
Quote:
* static int const value =
* * Item<I-1>::value + Item<I-2>::value;
>
Quote:
};
>
Quote:
template <>
struct Item<0{
>
Quote:
* static
* void put ( int* where ) {
* * where[0] = Item<0>::value;
* }
>
Quote:
* static int const value = 1;
>
Quote:
};
>
Quote:
template <>
struct Item<1{
>
Quote:
* static
* void put ( int* where ) {
* * where[0] = Item<0>::value;
* * where[1] = Item<1>::value;
* }
>
Quote:
* static int const value = 1;
>
Quote:
};
>
Quote:
template < int N >
struct Array {
>
Quote:
* Array() {
* * Item<N-1>::put( data );
* }
>
Quote:
* int data[N];
>
Quote:
};
>
Quote:
#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>
>
Quote:
int main()
{
* * Array<5items;
* * std::copy( items.data, items.data+5,
* * * * * * * *std::ostream_iterator<int>( std::cout, "\n" ) );
* * /* do stuff with items */
* * return 0;
>
Quote:
}
>
Quote:
The array itself is populated at runtime in the constructor of Array. I
don't see a way to push that into compile time.
>
Quote:
Best
>
Quote:
Kai-Uwe Bux
>
Alright, so I'm getting a little closer and now I've at least got code
that compiles
>
struct Bar
{
* * int X() { return -1; }
>
};
>
template <int I>
struct Foo : Bar {};
>
template <>
struct Foo<0>
{
* * int X() { return 0; }
>
}
>
template <int N>
class Array
{
* * Bar data[N];
>
}
>
int main()
{
* * // Now I need to figure out how doing this ...
* * Array<3array1;
>
* * // ... can essentially result in this
* * Bar array2[3] = {Foo<0>(), Foo<1>(), Foo<2>()};
>
}
>
>
So after more experimentation and testing I've got this working and
the solution is pretty straight forward


struct Bar
{
virtual int X() { return -1; }
};

template <int I>
struct Foo : Bar
{
virtual int X() { return I; }
};

template <>
struct Foo<0: Bar
{
virtual int X() { return 50; }
};

template <int N>
class Array
{
public:
Array() { Init(m_data); }

Bar* operator[] (int i) { return m_data[i]; }

protected:
friend class Array<N+1>;

// Recursively initialize our array
static void Init(Bar** data)
{
data[N] = new Foo<N>();
Array<N-1>::Init(data);
}

Bar* m_data[N+1];
};

template <>
class Array<0>
{
protected:
friend class Array<1>;

// Stop the recursion
static void Init(Bar** data)
{
data[0] = new Foo<0>();
}
};

int main()
{
Array<3array;
for (int i=0; i <= 3; i++)
{
printf("value: %d\n", array[i]->X());
}
}

value: 50
value: 1
value: 2
value: 3
Alex
Guest
 
Posts: n/a
#7: Oct 12 '08

re: Templated array of templates specialized by array index


On 10月12日, 上午11时03分, npan...@gmail.com wrote:
Quote:
On Oct 11, 4:41 pm, npan...@gmail.com wrote:
>
>
>
>
>
Quote:
On Oct 11, 3:20 pm, Kai-Uwe Bux <jkherci...@gmx.netwrote:
>
Quote:
Quote:
npan...@gmail.com wrote:
template <int I>
class Item
{
int X() { /*do default */ }
}
>
Quote:
Quote:
template <>
class Item<0>
{
int X() { /* do something special */ }
};
>
Quote:
Quote:
template <int N>
class Array
{
// The following obviously won't work
// How do I push this type of initialization to compile time???
Array()
{
for(int i=0; i<N; i++)
{
data[i] = Item<i>();
}
}
>
Quote:
Quote:
Item data[N];
}
>
Quote:
Quote:
int main()
{
Array<5items;
/* do stuff with items */
return 0;
}
>
Quote:
Quote:
Based on your code:
>
Quote:
Quote:
template <int I>
struct Item {
>
Quote:
Quote:
static
void put ( int* where ) {
Item<I-1>::put( where );
where[i] = Item<I>::X();
}
>
Quote:
Quote:
static
int X() {
return ( Item<I-1>::X() + Item<I-2>::X() );
}
>
Quote:
Quote:
};
>
Quote:
Quote:
template <>
struct Item<0{
>
Quote:
Quote:
static
void put ( int* where ) {
where[0] = Item<0>::X();
}
>
Quote:
Quote:
static
int X() {
return ( 1 );
}
>
Quote:
Quote:
};
>
Quote:
Quote:
template <>
struct Item<1{
>
Quote:
Quote:
static
void put ( int* where ) {
where[0] = Item<0>::X();
where[1] = Item<1>::X();
}
>
Quote:
Quote:
static
int X() {
return ( 1 );
}
>
Quote:
Quote:
};
>
Quote:
Quote:
template < int N >
struct Array {
>
Quote:
Quote:
Array() {
Item<N-1>::put( data );
}
>
Quote:
Quote:
int data[N];
>
Quote:
Quote:
};
>
Quote:
Quote:
#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>
>
Quote:
Quote:
int main()
{
Array<5items;
std::copy( items.data, items.data+5,
std::ostream_iterator<int>( std::cout, "\n" ) );
/* do stuff with items */
return 0;
>
Quote:
Quote:
}
>
Quote:
Quote:
Note, however, that the computation is not really done at compile time since
the static functions are executed at runtime. The following fixes at least
that:
>
Quote:
Quote:
template <int I>
struct Item {
>
Quote:
Quote:
static
void put ( int* where ) {
Item<I-1>::put( where );
where[i] = Item<I>::value;
}
>
Quote:
Quote:
static int const value =
Item<I-1>::value + Item<I-2>::value;
>
Quote:
Quote:
};
>
Quote:
Quote:
template <>
struct Item<0{
>
Quote:
Quote:
static
void put ( int* where ) {
where[0] = Item<0>::value;
}
>
Quote:
Quote:
static int const value = 1;
>
Quote:
Quote:
};
>
Quote:
Quote:
template <>
struct Item<1{
>
Quote:
Quote:
static
void put ( int* where ) {
where[0] = Item<0>::value;
where[1] = Item<1>::value;
}
>
Quote:
Quote:
static int const value = 1;
>
Quote:
Quote:
};
>
Quote:
Quote:
template < int N >
struct Array {
>
Quote:
Quote:
Array() {
Item<N-1>::put( data );
}
>
Quote:
Quote:
int data[N];
>
Quote:
Quote:
};
>
Quote:
Quote:
#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>
>
Quote:
Quote:
int main()
{
Array<5items;
std::copy( items.data, items.data+5,
std::ostream_iterator<int>( std::cout, "\n" ) );
/* do stuff with items */
return 0;
>
Quote:
Quote:
}
>
Quote:
Quote:
The array itself is populated at runtime in the constructor of Array.I
don't see a way to push that into compile time.
>
Quote:
Quote:
Best
>
Quote:
Quote:
Kai-Uwe Bux
>
Quote:
Alright, so I'm getting a little closer and now I've at least got code
that compiles
>
Quote:
struct Bar
{
int X() { return -1; }
>
Quote:
};
>
Quote:
template <int I>
struct Foo : Bar {};
>
Quote:
template <>
struct Foo<0>
{
int X() { return 0; }
>
Quote:
}
>
Quote:
template <int N>
class Array
{
Bar data[N];
>
Quote:
}
>
Quote:
int main()
{
// Now I need to figure out how doing this ...
Array<3array1;
>
Quote:
// ... can essentially result in this
Bar array2[3] = {Foo<0>(), Foo<1>(), Foo<2>()};
>
Quote:
}
>
So after more experimentation and testing I've got this working and
the solution is pretty straight forward
>
struct Bar
{
virtual int X() { return -1; }
>
};
>
template <int I>
struct Foo : Bar
{
virtual int X() { return I; }
>
};
>
template <>
struct Foo<0: Bar
{
virtual int X() { return 50; }
>
};
>
template <int N>
class Array
{
public:
Array() { Init(m_data); }
>
Bar* operator[] (int i) { return m_data[i]; }
>
protected:
friend class Array<N+1>;
>
// Recursively initialize our array
static void Init(Bar** data)
{
data[N] = new Foo<N>();
Array<N-1>::Init(data);
}
>
Bar* m_data[N+1];
>
};
>
template <>
class Array<0>
{
protected:
friend class Array<1>;
>
// Stop the recursion
static void Init(Bar** data)
{
data[0] = new Foo<0>();
}
>
};
>
int main()
{
Array<3array;
for (int i=0; i <= 3; i++)
{
printf("value: %d\n", array[i]->X());
}
>
}
>
value: 50
value: 1
value: 2
value: 3- 隐藏被引用文字 -
>
- 显示引用的文字 -
Be more correct ,you should wirte as following
////////////
template <int I>
struct Foo : public Bar
{
virtual int X() { return I; }
};

template <>
struct Foo<0: public Bar
{
virtual int X() { return 50; }


};
////////////
Closed Thread