1

我需要一系列使用可变数量值的初始化函数。我正在使用它们来实现与 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)?

我想保留逗号分隔值的语法,因为我希望它在某些情况下会产生编译时初始化(constfromindex)。不过,我的这个假设可能是错误的。初始化列表可以有 1 到 16 个值 - 无需担心空列表。

4

2 回答 2

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)
    {
    }
};

这很好地产生了相同的效果,但静态(无循环)。

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

于 2012-11-14T13:56:20.677 回答
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给递归的问题等)

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

于 2012-11-14T12:11:19.320 回答