可变长度初始化程序的模板

时间:2012-11-14 09:42:06

标签: c++ templates eigen

我需要一系列初始化函数,使用可变数量的值。我正在使用它们来实现与Eigen库的收集操作。这是我现在使用每个向量长度的一个模板的方式:

template<typename T1, typename T2>
inline void gather (Array<T1,4,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,4,1> &index) 
{
    to << from[index[0]], from[index[1]], from[index[2]], from[index[3]];
}

template<typename T1, typename T2>
inline void gather (Array<T1,6,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,6,1> &index) 
{
    to << from[index[0]], from[index[1]], from[index[2]], from[index[3]], from[index[4]], from[index[5]];
}

有没有办法用一个参数化长度参数的模板(上面的代码段中的4和6)替换上面模板的更长列表?如果是这样,是否可以使用预C ++ 11语言规范(我使用的是Visual Studio 2010)?

我想保留逗号分隔值语法,因为我希望在某些情况下可能会产生编译时初始化(const fromindex)。我可能在这个假设中错了。初始化列表可以包含1到16个值 - 无需担心空列表。

2 个答案:

答案 0 :(得分:2)

基于重载operator,运算符来概括这种语法是非常棘手的,结果看起来很尴尬(如果它有效)。我建议尝试其他选项(例如,转到MatrixBase::operator<<(DenseBase&)运算符)。

如果你还想要它,你必须逐个解包标量:

template<typename T1, typename T2, class CI, int Current, int Height>
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index, CI&& ci, std::integral_constant<int, Current>*)
{
  gather(to, from, index, (ci,from[index[Current]]), (std::integral_constant<int, Current+1>*)0);
}

template<typename T1, typename T2, class CI, int Height>
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index, CI&& ci, std::integral_constant<int, Height>*) {}

template<typename T1, typename T2, int Height>
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index) {
  gather(to, from, index, (to << index[from[0]]), (std::integral_constant<int, 1>*)0);
}

丑陋,可能存在问题(如果可能,您需要处理Dynamic值,零高度,将CommaInitializers传递给递归等可能会出现问题。)

另外,它具有线性模板实例化深度(在这种情况下,恕我直言,这是不可避免的)。

答案 1 :(得分:2)

在此设置中不要使用逗号初始化程序语法,这会很麻烦。在使用文字时,此语法用于可读性,而不是您的情况。

相反,我会建议像:

template<typename T1, typename T2, unsigned int SIZE, unsigned int INDEX>
struct gather {
   gather(Array<T1,SIZE,1> &to, 
          const Array<T2,Dynamic,1> &from, 
          const Array<int,SIZE,1> &index) 
   {
      to.col(INDEX) = from[index[INDEX]];
      gather<T1,T2,SIZE,INDEX+1>(to,from, index);
   }
};

template<typename T1, typename T2, unsigned int SIZE>
struct gather<T1,T2,SIZE,SIZE>{
    gather(Array<T1,SIZE,1> &to, 
           const Array<T2,Dynamic,1> &from, 
           const Array<int,SIZE,1> &index)
    {
    }
};

很好地产生相同的效果,但是静态地(没有循环)。

我在这里使用一个结构,因为函数的部分模板特化限制,但由于内联,它应该归结为相同。