x,y,z和带有x(),y(),z()的点的模板函数

问题描述:

我用点云工作很多,所以我使用了很多PCL和Eigen库。 PCL中的点有一个.x .y和.z的公共成员。特征点有.x().y()和.z()x,y,z和带有x(),y(),z()的点的模板函数

我经常发现自己写了一个点类型的函数,然后通过创建一个临时点将其从一种类型转换为另一种类型来调用它:

eg

为了进一步复杂化的问题,PCL点来在各种类型:XYZ,XYZRGB,XYZN等(参见http://pointclouds.org/documentation/tutorials/adding_custom_ptype.php)和特征向量有几种类型,以及:为的Vector3D双打和Vecto3f为浮筒,这两种矩阵类型的专业化(见http://eigen.tuxfamily.org/dox/group__matrixtypedefs.html

我想知道是否可能有一些模板专业化魔术咒语可以被调用,以避免这种情况,即它会检测点类型是否有.x()或一个.x并适当地使用。

如果你不想大惊小怪周围SFINAE,您可以使用内置的地图尼斯在PCL和使用本征函数投

而不是构建您的Eigen::Vector3d类型,并把它传递给f(),你可以请执行下列操作

pcl::PointXYZ p; 
f(p.getVector3fMap().cast<double>); 

getVector3fMap()适用于所有内置PCL类型。

+0

我不确定,但我认为这样可以为您节省施工操作,因为您并未构建临时设备。 – pikeyboom 2015-10-21 13:49:14

为了检测如果一个类具有特定名称的方法或成员变量,可以用经典的SFINAE的方法:

template<typename T> 
class has_x { 
    private: 
     typedef char yes[1]; 
     typedef char no[2]; 

     template<typename U> static yes& test_member(decltype(U::x)); 
     template<typename U> static no& test_member(...); 

     template<typename U, U> struct check; 
     template<typename U> static yes& test_method(check<float (U::*)(), &U::x>*); 
     template<typename U> static no& test_method(...); 

    public: 
     static const bool as_method = (sizeof(test_method<T>(0)) == sizeof(yes)); 
     static const bool as_member = (sizeof(test_member<T>(0)) == sizeof(yes)); 
}; 

其可以在微小的测试套件进行测试:

struct something_else { 
}; 

struct fn_vec { 
    float x() const { return 66; }; 
}; 

struct mem_vec { 
    mem_vec() : x(55) {}; 
    float x; 
}; 

int main(int argc, char*argv[]) { 
    std::cout << "fv: " << has_x<fn_vec>::as_method << std::endl; 
    std::cout << "mv: " << has_x<mem_vec>::as_method << std::endl; 
    std::cout << "se: " << has_x<something_else>::as_method << std::endl; 

    std::cout << std::endl; 

    std::cout << "fv: " << has_x<fn_vec>::as_member << std::endl; 
    std::cout << "mv: " << has_x<mem_vec>::as_member << std::endl; 
    std::cout << "se: " << has_x<something_else>::as_member << std::endl; 

    return 0; 
} 

,输出:

fv: 1 
mv: 0 
se: 0 

fv: 0 
mv: 1 
se: 0 

可以再用使用编写特定于每种类型的函数或结构的变体。您也可以使用logical operators in std::enable_if's condition来创建任何您需要的条件组合。

在同一个测试框架是一个愚蠢的例子如上:

template<typename T> 
typename std::enable_if<has_x<T>::as_method, float>::type getX(const T& v) { 
    return v.x(); 
} 

template<typename T> 
typename std::enable_if<has_x<T>::as_member, float>::type getX(const T& v) { 
    return v.x; 
} 

template<typename T> 
void foo(const T& val) { 
    std::cout << getX(val) << std::endl; 
} 

int main(int argc, char*argv[]) { 
    fn_vec fn; 
    mem_vec mem; 

    foo(fn); 
    foo(mem); 

    return 0; 
} 

,输出:

66 
55 

这应该希望给你你需要创建通用框架,所有的工具。因为所有东西都是模板化的,所以它的大部分都应该通过编译器进行优化,最终达到合理的效率。

所有在Linux上的GCC 4.8.2测试过,但它应该在任何C++ 11编译器中工作。

+0

这太好了。原来,pikeyboom为我的Eigen/PCL示例提供了一个更简单的解决方案,但是我还有其他一些可以使用SFINAE方法的情况。感谢您的详细示例 – 2015-10-22 17:50:37