在一个项目中,我有几个类,其中包括实现为静态数组的矩阵,例如:
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 }
};
我想实现一个元函数,它提供逆映射,从StaticContainer :: e中的一列回到第二个索引(在本例中为1-4)。理想情况下,这样的事情:
template< typename TContainer, short TeX, short TeY >
struct VectorToIndex
{
enum { value = ??? };
};
最后,我想通过(如果可能的话):
BOOST_STATIC_ASSERT( 0 == VectorToIndex< StaticContainer, -1, 0 >::value );
这有可能吗?我最初尝试递归搜索“e”矩阵失败了,因为无论何时我尝试访问(在编译时)我得到的条目(GCC):
error: ‘StaticContainer::e’ cannot appear in a constant-expression
我是否理解矩阵中的值在编译时不可用?
我将不胜感激。我可以自由地改变矩阵初始化/存储的方式(所以我想到了一些编译时注册机制)。唯一的限制是在编译时获得这种逆映射。
澄清:
电子矩阵中的每列表示空间方向(在这种情况下,2D)。保证列不同。
我希望以下来自元函数的结果:
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
如果使用无效的数字组合(即矩阵中不是列)实例化此模板,我想产生编译错误。
答案 0 :(得分:0)
您的声明中存在不匹配:
typename TContainer
表示模板参数是StaticContainer::e
是一个值无法比拟。
我可以想到一些潜在的解决方案,但第一个问题显然是:为什么不手动构建反向矩阵并使用assert
来证明其正确性?它当然更简单,简单就是美丽。
答案 1 :(得分:0)
正如所承诺的,这里有一个解决方案。我没有使用可变参数模板重新构建整个元编程库,而是利用这个机会尝试使用boost mpl,结果证明它非常富有表现力。使用它,VectorToIndex将如下所示:
template<typename basis, typename axis>
struct VectorToIndex :
boost::mpl::if_<
boost::mpl::greater<boost::mpl::size<basis>, typename boost::mpl::find<basis, axis>::type::pos>,
typename boost::mpl::find<basis, axis>::type::pos,
boost::mpl::empty_base
>::type
{
};
如果“基础”中存在“轴”,则VectorToIndex<basis, axis>::value
等于[0,基础大小]范围内的索引。如果不是这样,则不定义VectorToIndex<basis, axis>::value
,因此访问它可能会产生编译时错误或
通过SFINAE选择性实现。
要表示轴,应使用boost :: mpl :: vector,如下所示:
typedef boost::mpl::vector<boost::mpl::int_<1>, boost::mpl::int_<0>, boost::mpl::int_<0> > e1;
typedef boost::mpl::vector<boost::mpl::int_<0>, boost::mpl::int_<1>, boost::mpl::int_<0> > e2;
typedef boost::mpl::vector<boost::mpl::int_<0>, boost::mpl::int_<0>, boost::mpl::int_<1> > e3;
考虑到上面的定义,我们有
VectorToIndex<boost::mpl::vector<e1, e2, e3>, e1>::value -> 0
VectorToIndex<boost::mpl::vector<e1, e2, e3>, e2>::value -> 1
VectorToIndex<boost::mpl::vector<e1, e2, e3>, e3>::value -> 2
VectorToIndex<boost::mpl::vector<e1, e2>, e3>::value -> COMPILE-TIME ERROR