Templates with constant array parameter

  • Thread starter Kristian Bisgaard Lassen
  • Start date
K

Kristian Bisgaard Lassen

Hi,

How do I parameterize a template by a a allocated array of integers,
which is declared static and constant, so I can make compile time
optimizations depending on the content of the array. The way I have
written my code makes g++ complain about it not being static.

BTW I am new to the C++ language and also the templates it provides.

Here is an example of what I want to do

template<bool condition, class Then, class Else>
struct IF {
typedef Then RET;
};

template<class Then, class Else>
struct IF<false, Then, Else> {
typedef Else RET;
};

struct A {
static void exec () {
cout << "yes" << endl;
}
};

struct B {
static void exec () {
cout << "no" << endl;
}
};

template<const int mask[]>
void foo () {
IF<mask[0] == 1,
A,
B>::RET::exec ();
}

struct Run {
static void run () {
static const int filter[] = {1,1,1};

foo<filter>();
}
};

int main () {
Run::run();

return 0;
}

I want the compiled code just to contain the instructions for

cout << "yes" << endl;

But as I said g++ complains and says

error: non-constant `((*&filter) == 1)' cannot be used as template
argument

The error is from the statement

IF<mask[0] == 1,
A,
B>::RET::exec ();

Hope their is someone who can tell me what I am doing wrong or if is
even possible make compiletime optimizations using arrays.

Best regards,
Kristian Bisgaard Lassen
 
K

Kristian Bisgaard Lassen

Hi,

I have found out that the modifier const on int* only promises that the
reference does not change. What it points to is not constant. Can you
make some sort of declearation so an array ints = {1,1,1} is constant
also on the content level? Ie. ints is statically an array of {1,1,1}.
That is basically what I need to make the example work.

An alternativ solution would be to use a pair, where the head of each
pair is an constant integer. But I would really like to use an array
somehow since it is a very convenient whay to specify a dataset.

Best regards,
Kristian Bisgaard Lassen
 
J

Jeff Schwab

Kristian said:
How do I parameterize a template by a a allocated array of integers,
which is declared static and constant, so I can make compile time
optimizations depending on the content of the array. The way I have
written my code makes g++ complain about it not being static.

The value of a boolean expression used as a tempate argument must be
determined at compile time. Even when enough information is available
to determine the value (as in the example code you posted), the compiler
may fail to do so. Sorry to be the bearer of bad news. :(
 
J

Jeff Schwab

Kristian said:
Hi,

I have found out that the modifier const on int* only promises that the
reference does not change. What it points to is not constant. Can you
make some sort of declearation so an array ints = {1,1,1} is constant
also on the content level? Ie. ints is statically an array of {1,1,1}.
That is basically what I need to make the example work.

int const * const; // constant pointer to constant int
int const *; // pointer to constant int
int * const; // constant pointer to int.
int *; // pointer to int
 
K

Kristian Bisgaard Lassen

Hi Jeff,
The value of a boolean expression used as a tempate argument must be
determined at compile time.

Yes that is also what I want.
Even when enough information is available
to determine the value (as in the example code you posted), the compiler
may fail to do so.

Why is that? Is it my C++ compiler, g++? Or is it because I have not
written the code so the compiler recognises it as being static? Ie. I
have only declared the pointer to be constant.

Best regards,
Kristian Bisgaard Lassen
 
T

tom_usenet

Hi,

How do I parameterize a template by a a allocated array of integers,
which is declared static and constant, so I can make compile time
optimizations depending on the content of the array. The way I have
written my code makes g++ complain about it not being static.

BTW I am new to the C++ language and also the templates it provides.

This is quite advanced for someone who is new to the language!
template<const int mask[]>
void foo () {
IF<mask[0] == 1,
A,
B>::RET::exec ();
}

As you've seen, that's illegal - performing an array lookup isn't a
compile time operation. The contents of arrays (const literal or not)
are never known to the compiler at compile time except where the array
is initialised.
I want the compiled code just to contain the instructions for

cout << "yes" << endl;

That is possible, using recursive lists of integers rather than
arrays. Two versions (both tested with GCC and Comeau C++) below:

#include <iostream>
using namespace std;

template<bool condition, class Then, class Else>
struct IF {
typedef Then RET;
};

template<class Then, class Else>
struct IF<false, Then, Else> {
typedef Else RET;
};

struct A {
static void exec () {
cout << "yes" << endl;
}
};

struct B {
static void exec () {
cout << "no" << endl;
}
};

template <int i, class Tail>
struct IntList
{
static int const value = i;
typedef Tail tail;
};

struct null_type{};

template <int i, class List>
struct AtIndex
{
typedef typename AtIndex<i - 1, typename List::tail>::type type;
};

template <class List>
struct AtIndex<0, List>
{
typedef List type;
};

template<class IntList>
void foo () {
IF<AtIndex<0, IntList>::type::value == 1,
A,
B>::RET::exec ();
}

struct Run {
static void run () {
foo<IntList<1, IntList<1, IntList<1, null_type> > > >();
}
};

int main () {
Run::run();

return 0;
}


Or using boost's MPL library (www.boost.org):

#include <boost/mpl/if.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/at.hpp>
using namespace boost::mpl;

#include <iostream>
using namespace std;

struct A {
static void exec () {
cout << "yes" << endl;
}
};

struct B {
static void exec () {
cout << "no" << endl;
}
};

template<class List>
void foo () {
if_c<
at_c<List, 0>::type::value == 1,
A,
B
::type::exec();
}

struct Run {
static void run () {
foo<vector_c<int, 1, 1, 1> >();
}
};

int main () {
Run::run();

return 0;
}

Tom
 
J

Jeff Schwab

Kristian said:
Hi Jeff,



Yes that is also what I want.



Why is that? Is it my C++ compiler, g++? Or is it because I have not
written the code so the compiler recognises it as being static? Ie. I
have only declared the pointer to be constant.

The post from tom_usenet on this thread explains quite eloquently. :)

If you want to get into metaprogramming, check out the Josuttis book on
templates. It was an eye opener for me.
 

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
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top