In a project, I have several classes which encapsulate, among other things, matrices implemented as static-arrays, e.g.:
struct StaticContainer
{
static const short e[2][4];
};
/// Initialize components of member-array (with external linkage).
const short StaticContainer::e[2][4] = {
{ -1, 0, 0, 1 },
{ 0, -1, 1, 0 }
};
I would like to implement a meta-function which provides the inverse-mapping, from a column in StaticContainer::e back to the second index (1-4 in this case). Ideally, something like this:
template< typename TContainer, short TeX, short TeY >
struct VectorToIndex
{
enum { value = ??? };
};
Finally, I would like to pass (if this is possible at all):
BOOST_STATIC_ASSERT( 0 == VectorToIndex< StaticContainer, -1, 0 >::value );
Is this possible at all? My initial attempts to recursively-search through the ‘e’-matrix failed, because whenever I try to access (at compile-time) the entries within I get (GCC):
error: ‘StaticContainer::e’ cannot appear in a constant-expression
Shall I understand that the values in the matrix are not available at compile-time?
I would appreciate any comments. I am free to change the way the matrix is initialized/stored (so I was thinking of some compile-time registration mechanism). The only constraint is to get this inverse-mapping at compile-time.
Clarifications:
-
Each column in the e-matrix represents a spatial direction (in this case, 2D). The columns are guaranteed to be distinct.
-
I would expect the following results from the meta-function:
VectorToIndex< StaticContainer, -1, 0 > --> '0' at compile-time VectorToIndex< StaticContainer, 0,-1 > --> '1' at compile-time VectorToIndex< StaticContainer, 0, 1 > --> '2' at compile-time VectorToIndex< StaticContainer, 1, 0 > --> '3' at compile-time
If this template is instantiated with an invalid combination of numbers (i.e. which is not a column in the matrix), I would like to produce a compilation-error.
- The solution I currently have is a simple program which writes files with the necessary template-instantiations manually. This satisfies the requirements (results are correct and for invalid vectors there is a compile-time error – since the corresponding template-instantiation is missing). However, since I have many classes similar to ‘StaticContainer’ in my codebase (many of them with larger matrices), this process generates thousands of lines of code :(.
As promissed, here goes a solution. Rather than reinventing a whole metaprogramming library using variadic templates, I used this opportunity to try out boost mpl and it turns out to be pretty expressive. Using it, VectorToIndex would look like the following:
If “axis” is present in “basis” then
VectorToIndex<basis, axis>::valueequals its index in the range [0, size-of-basis). If otherwise this is not true, thanVectorToIndex<basis, axis>::valueis not defined, thus accessing it may be used to produce compile-time errors orselective instanciation through SFINAE.
To represent the axis one should use boost::mpl::vector, like shown below:
Considering the definitions above, one has