2013-02-28 114 views
5

在MATLAB中,可以寫成:如何將雙參數函數轉換爲單參數函數?

S = @(x,y) x^2+y^2-1 
G = @(x) S(x,1); 

如果我有一個函數期待一個參數的功能,我可以做上面。我如何在c/C++中做到這一點?

我有一個庫函數(來自CGAL庫),期望作爲參數一個函數,它本身只有一個參數。理想情況下,我有一個類(SphericalHarmonics),我想有一個成員函數接受一個參數。所以,我有:

FT SphericalHarmonics::distFunction(Point_3 p) 

(注意:FT類似於double一種類型),但當然,當我嘗試

SphericalHarmonics *sh = new SphericalHarmonics(1); 
Surface_3 surface(sh->distFunction, Sphere(ORIGIN,2.)); 

this也被視爲一個說法,我distFunction功能是雙參數函數,並引發錯誤。

注意,這可以用全局變量來解決,即

SphericalHarmonics *sh; 
FT dist_function(Point_3 p) { 
    return sh->distFunction(p); 
} 

main() { 
    sh = new SphericalHarmonics(1); 
    Surface_3 surface(dist_function); 
} 

然而,這確實是不理想的。我想要一個沒有全局變量的方法,因爲能夠有一個可以輕鬆集成CGAL庫的類函數會更好。

在此先感謝!

[增訂]

@安迪警車:我想你std::bindlambda解決方案,但似乎仍然運行到錯誤,至於參數的個數。

當在main,我使用的代碼:

SphericalHarmonics *sh = new SphericalHarmonics(cInit, numL, symm); 
auto fxn = std::bind(&SphericalHarmonics::distFunction, sh, std::placeholders::_1); 
Surface_3 surface(fxn, Sphere_3(ORIGIN,2.)); 

我得到的錯誤:

~/lib/basisfunctions/SphericalHarmonics2/mesh_an_implicit_function.cpp:62:48: 
error: no matching function for call to  
‘CGAL::Implicit_surface_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, 
double (*) 
(CGAL::Point_3<CGAL::Epick>)>::Implicit_surface_3(std::_Bind<std::_Mem_fn 
<double (SphericalHarmonics::*)(CGAL::Point_3<CGAL::Epick>)> 
(SphericalHarmonics*, std::_Placeholder<1>)>&, Sphere_3)’ 

~/CGAL-4.1/include/CGAL/Implicit_surface_3.h:50:5: note: no known conversion 
for argument 1 from ‘std::_Bind<std::_Mem_fn<double (SphericalHarmonics::*) 
(CGAL::Point_3<CGAL::Epick>)>(SphericalHarmonics*, std::_Placeholder<1>)>’ to 
‘CGAL::Implicit_surface_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, 
double (*)(CGAL::Point_3<CGAL::Epick>)>::Function 
{aka double (*)(CGAL::Point_3<CGAL::Epick>)}’ 

~/CGAL-4.1/include/CGAL/Implicit_surface_3.h:34:9: note: 
candidate expects 1 argument, 2 provided 

[增訂]

現在很清楚,我認爲我需要其可以被轉換爲一個函數指針的函數(即surface需要函數指針參數)。這排除了std::bind選項。此外,如果它捕獲變量(capture-less vs. capturing lambdas),看起來lambda不能被轉換爲函數指針。所以我認爲Andy-Prowl的回答總的來說是這個問題的正確答案,但我需要找到一個不同的解決方法。

+3

(我還沒有真正閱讀問題)綁定或拉姆達? – 2013-02-28 00:15:33

+0

這些標籤有誤導性,應該包含matlab/lambda – Dmitry 2013-02-28 00:25:03

+0

這些解決方案中的任何一個都可以正常工作嗎?是不是可以使用bind來代替函數指針? – 2014-09-04 21:36:07

回答

5

選項1:

如果你的成員函數並不暗示對你的類的實例工作(並因此不需要接收this指針),你可以使它static

class SphericalHarmonics 
{ 
    ... 
    static double distFunction(Point p); 
    ... 
}; 

double SphericalHarmonics::distFunction(Point p) 
{ 
    ... 
} 

現在,您的功能將有效地具有一個參數:

surface(SphericalHarmonics::distFunction); 

選項2:

否則,您可以使用​​討好成員函數distFunction和修復其第一,隱含參數(如果您不與C++編譯器11的工作,你可以從Boost.Bind庫使用等效boost::bind()):

#include <functional> 

SphericalHarmonics *sh = new SphericalHarmonics(1); 
auto fxn = std::bind(&SphericalHarmonics::distFunction, sh, _1); 
surface(fxn); 

OPTION 3:

另外,在C++ 11,一個lambda可以做的工作:

SphericalHarmonics *sh = new SphericalHarmonics(1); 
auto fxn = [=] (double d) { return sh->distFunction(d); } 
+0

謝謝!我確信這是正確的,所以我已經檢查過了。選項1不是一個選項(我想處理特定的類實例)。當我嘗試選擇2或3時,我得到錯誤'錯誤:'fxn'沒有命名一個類型'和'錯誤:'fxn'沒有在這個範圍內聲明。我試過'std :: bind'和'boost :: bind'(包括''和''),我得到了同樣的錯誤。在Ubuntu 12.04上使用gcc 4.6.3版本 – OwenM 2013-02-28 01:10:33

+0

@OwenM:你是否在使用帶有-std = C++ 0x或者-std = C++ 11命令行選項的C++ 11編譯器? 'auto'關鍵字需要C++ 11。我也建議你升級到GCC 4.7.2,你使用的版本是相當老的。還有[這個網站](http://www.liveworkspace.org),你可以用不同的編譯器編譯你的代碼。 – 2013-02-28 01:17:20

+0

是的,gcc 4.7.2與-std = C++ 11修復了這個問題! – OwenM 2013-02-28 17:00:51

5

使用std::bindboost::bind

#include <functional> 

SphericalHarmonics *sh = new SphericalHarmonics(1); 
surface(std::bind(&SphericalHarmonics::distFunction, sh, _1)); 
+1

你的意思是sh而不是這個? – Slava 2013-02-28 00:20:23

+0

@Slava是的,謝謝。 – Drax 2013-02-28 00:21:17

1

在處理CGAL的模板Surface_3類的具體情況。你可能會使用這樣的事情(從他們的例子)來定義Surface_3類型:

typedef CGAL::Surface_mesh_default_triangulation_3 Tr; 
// c2t3 
typedef CGAL::Complex_2_in_triangulation_3<Tr> C2t3; 
typedef Tr::Geom_traits GT; 
typedef GT::Sphere_3 Sphere_3; 
typedef GT::Point_3 Point_3; 
typedef GT::FT FT; 
typedef FT (*Function)(Point_3); 
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3; 

這是誤導,因爲它使得它看起來像CGAL的等值類只能用函數指針處理(而不是std::function等等。)。但問題是我們只有這樣定義它。簡單地定義Surface_3使用std::function<FT (Point_3)>作爲模板參數和Andy Prowl's answerstd::bind和lambda表達式會工作得很好:

... 
typedef std::function<FT (Point_3)> Function; 
typedef CGAL::Implicit_surface_3<GT, Function> Surface_3; 
相關問題