特征分配器导致模板类故障

时间:2015-12-13 20:35:34

标签: c++ std eigen templating

我有这堂课:

typedef vector<Eigen::Affine3d,Eigen::aligned_allocator<Eigen::Affine3d> > VoteList;

template <class T>
class KernelDensityEstimator {

  public:
    KernelDensityEstimator() {}

    void setData(vector<T>& d) {
      data = d;
    }

    void setKernel(double (*k)(T&, T&)) {
      kernel = k;
    }

    double evaluate(T& p) {
      double sum;
      for (int i = 0; i < data.size(); i++) {
        sum += (*kernel)(p, data[i]);
      }
      return sum/data.size();
    }

  private:
    double (*kernel) (T&, T&);
    vector<T> data;

};

我现在想使用T = Eigen :: Affine3d类型。但是,当我打电话给setData()时,它会给我带来麻烦,因为Eigen需要为std容器指定一个Eigen :: aligend_allocator来与Eigen一起使用。

因此,当我将vector<Eigen::Affine3d,Eigen::aligned_allocator<Eigen::Affine3d> >(又名VoteList)作为setData()的输入参数时,我的编译器抱怨:

no known conversion for argument 1 from ‘VoteList {aka std::vector<Eigen::Transform<double, 3, 2>, Eigen::aligned_allocator<Eigen::Transform<double, 3, 2> > >}’ to ‘std::vector<Eigen::Transform<double, 3, 2>, std::allocator<Eigen::Transform<double, 3, 2> > >&’

哪种有意义,但我认为分配器是对象类型的一部分。有没有解决方法并保持我的KernelDensityEstimator通用?

2 个答案:

答案 0 :(得分:1)

您基本上希望为您的成员data设置不同的类型,具体取决于类模板参数类型T。有几种方法可以做到这一点,这里有一个建议:

  • 为您的类定义一种特殊的存储类型,您可以在其中保存数据(最好将其放在合适的命名空间或类中):

    //normal storage type
    template<typename T>
    struct storage_type_impl
    {
        using type = std::vector<T>;
    };
    
    //storage type for Eigen::Transform types
    template<typename ... Args>
    struct storage_type_impl<Eigen::Transform<Args ...> >
    {
        using type = std::vector<Eigen::Transform<Args ...>
                               , Eigen::aligned_allocator<Eigen::Transform<Args ...> > >;
    };
    
    template<typename T>
    using storage_type = typename storage_type_impl<T>::type;
    
  • 现在您可以在类中使用它,并使用模板setData方法(如果编译器无法执行数据复制/移动,它仍然会抱怨):

    template <class T>
    struct KernelDensityEstimator
    {
        template<typename D>
        auto setData(D&& d)
        {
            data = std::forward<D>(d);  //calls move assignment if d is an rvalue
                                        //otherwise a copy is performed
        }
        //...
    
    private:
        storage_type<T> data;
        //...
    };    
    

代码未经测试,因为我目前没有Eigen可用,但我希望它仍能解释基本想法。

答案 1 :(得分:1)

您可以为您计划使用的类型启用Eigen的std :: vector特化,详见there,例如:

#include<Eigen/StdVector>
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Affine3d)
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Matrix4d)
...