2014-12-05 165 views
2

我用點雲工作很多,所以我使用了很多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並適當地使用。

回答

1

如果你不想大驚小怪周圍SFINAE,您可以使用內置的地圖尼斯在PCL和使用本徵函數投

而不是構建您的Eigen::Vector3d類型,並把它傳遞給f(),你可以請執行下列操作

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

getVector3fMap()適用於所有內置PCL類型。

+0

我不確定,但我認爲這樣可以爲您節省施工操作,因爲您並未構建臨時設備。 – pikeyboom 2015-10-21 13:49:14

1

爲了檢測如果一個類具有特定名稱的方法或成員變量,可以用經典的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

相關問題