A shot in the dark, as I'm not sure what exactly it is you want to do.
It seems like you want to make some compile-time decisions, which could look something like this:
enum EHWUnit
{
Unit0,
Unit1,
Unit2
};
enum EHWType
{
Type1,
Type2,
Type3,
Type4
};
template <int Select>
struct ArrayIS
{
static constexpr int const array[] = {1, 3, 5, 7, 9};
};
template <int Select>
constexpr int const ArrayIS<Select>::array[];
template <>
struct ArrayIS<0>
{
static constexpr int const array[] = {2, 4, 6, 8, 10};
};
constexpr int const ArrayIS<0>::array[];
template <EHWUnit aUnit, EHWType aHWType, int aSelect>
struct SelectHWinput
{
static constexpr int get()
{
return ArrayIS<static_cast<int>(aHWType) & 1>::array[aSelect];
}
};
int main()
{
// To illustrate that the value is selected at compile-time, a
// static assertion that will always fail:
static_assert(SelectHWinput<Unit0, Type1, 0>::get() < 0, "Works, value selected at compile-time");
}
In the code above, Template Metaprogramming (TMP) is used to select a value of one of the arrays at compile-time. The correct array is chosen by supplying the Select
template non-type parameter. Because these arrays are declared constexpr
, a constexpr
member-function can be used to extract one of its element at compile-time. The static_assert
proves that it works.
If you want to construct the arrays more flexibly at compile-time, I suggest looking at this question of mine, where I describe TMP-functors to construct static arrays at compile-time:
g++ (4.7.2) bug or feature, when initializing static arrays at compile-time?
EDIT:
You said you were interested in the Array
implementation:
template <typename T, size_t Count, template <typename, T> class Function, T Current, T ... Elements>
struct Array_: public Array_<T, Count - 1, Function, Function<T, Current>::result, Elements ..., Current>
{};
template <typename T, template <typename, T> class Function, T Current, T ... Elements>
struct Array_<T, 0, Function, Current, Elements...>
{
constexpr static std::array<T, sizeof...(Elements)> array = {{Elements ...}};
};
template <typename T, size_t Count, T Start = T(), template <typename, T> class Function = Null>
struct Array: public Array_<T, Count, Function, Start>
{};
Here, the last one is the one you'll use, using a Template Metaprogramming functor that tells the compiler how to generate the next element from the previous one. This is a limitation, but it's the best I could come up with at the time.
Three simple functors that you could use:
template <typename T, T Value>
struct Null
{
enum { result = Value };
};
template <typename T, T Value>
struct Increment
{
enum { result = Value + 1 };
};
template <typename T, T Value>
struct Decrement
{
enum { result = Value - 1 };
};
For example, if you need an array with incremental values from 1 to 100, you would do this:
std::array<int, 100> arr = Array<int, 100, 1, Increment>::array;
This array is then allocated and populated at compile-time.