Re: Templated array of templates specialized by array index
On Oct 11, 4:41 pm, npan...@gmail.com wrote:
On Oct 11, 3:20 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
npan...@gmail.com wrote:
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<5> items;
/* 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<5> items;
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 le=
ast
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<5> items;
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<3> array1;
// ... 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<3> array;
for (int i=0; i <= 3; i++)
{
printf("value: %d\n", array[i]->X());
}
}
value: 50
value: 1
value: 2
value: 3