2012-10-25 18 views
6

के साथ जीएसएल का उपयोग करते समय स्थैतिक सदस्य फ़ंक्शन से कैसे बचें I सदस्य पदों को static के रूप में घोषित किए बिना सी ++ कक्षा के भीतर जीएसएल का उपयोग करना चाहते हैं। इसका कारण यह है क्योंकि मैं उन्हें बहुत अच्छी तरह से नहीं जानता और मुझे थ्रेड सुरक्षा के बारे में निश्चित नहीं है। जो मैंने पढ़ा है, std::function एक समाधान हो सकता है लेकिन मुझे यकीन नहीं है कि इसका उपयोग कैसे किया जाए।सी ++

मेरा प्रश्न g की घोषणा में static को कैसे हटा सकता है?

#include<iostream> 
#include <functional> 
#include <stdlib.h> 
#include <gsl/gsl_math.h> 
#include <gsl/gsl_monte.h> 
#include <gsl/gsl_monte_plain.h> 
#include <gsl/gsl_monte_miser.h> 
#include <gsl/gsl_monte_vegas.h> 


using namespace std; 

class A { 
public: 
    static double g (double *k, size_t dim, void *params) 
    { 
    double A = 1.0/(M_PI * M_PI * M_PI); 
    return A/(1.0 - cos (k[0]) * cos (k[1]) * cos (k[2])); 
    } 
    double result() { 
    double res, err; 

    double xl[3] = { 0, 0, 0 }; 
    double xu[3] = { M_PI, M_PI, M_PI }; 

    const gsl_rng_type *T; 
    gsl_rng *r; 

    ////// the following 3 lines didn't work /////// 
    //function<double(A,double*, size_t, void*)> fg; 
    //fg = &A::g; 
    //gsl_monte_function G = { &fg, 3, 0 }; 
    gsl_monte_function G = { &g, 3, 0 }; 

    size_t calls = 500000; 

    gsl_rng_env_setup(); 

    T = gsl_rng_default; 
    r = gsl_rng_alloc (T); 

    { 
     gsl_monte_plain_state *s = gsl_monte_plain_alloc (3); 
     gsl_monte_plain_integrate (&G, xl, xu, 3, calls, r, s, &res, &err); 
     gsl_monte_plain_free (s); 
    } 

    gsl_rng_free (r); 
    return res; 
    } 
}; 

main() { 
    A a; 
    cout <<"gsl mc result is " << a.result() <<"\n"; 
} 

अद्यतन (1):

मैं gsl_monte_function G = { bind(&A::g, this,_1,_2,_3), 3, 0 }; करने के लिए gsl_monte_function G = { &g, 3, 0 }; बदल रहा करने की कोशिश की लेकिन यह

अद्यतन (2) काम नहीं किया: मैं assigning std::function to a member function का उपयोग कर की कोशिश की लेकिन यह 'नहीं था टी काम करते हैं।

अद्यतन (3) अंत में मैं एक गैर सदस्य समारोह लिखा है:

double gmf (double *k, size_t dim, void *params) { 
    auto *mf = static_cast<A*>(params); 
    return abs(mf->g(k,dim,params)); 
    //return 1.0; 
}; 

यह काम किया लेकिन यह एक गंदा समाधान है क्योंकि मैं एक सहायक समारोह लिखने के लिए की जरूरत है। लैम्बडास, फ़ंक्शन और बाइंड के साथ, वर्ग के भीतर सब कुछ तार्किक रखने का एक तरीका होना चाहिए।

+0

मुझे पता है कि मेरा उत्तर काफी देर से आया देखते हैं, लेकिन मुझे आशा है कि रैप वर्ग भविष्य में आप कर सकते हैं। यह रैप काफी आसान है क्योंकि यह आपको लैम्ब्डा फ़ंक्शंस को एकीकृत करने या एक से अधिक पैरामीटर के साथ फ़ंक्शंस को बाध्य करने की अनुमति देता है (यदि आप f (x, a) = x को एकीकृत करना चाहते हैं जहां उदाहरण के लिए पैरामीटर है)। –

उत्तर

7

आप आसानी से सदस्य कार्यों निम्नलिखित कोड (जो एक अच्छी तरह से ज्ञात समाधान है) का उपयोग कर लपेट कर सकते हैं

class gsl_function_pp : public gsl_function 
{ 
    public: 
    gsl_function_pp(std::function<double(double)> const& func) : _func(func){ 
     function=&gsl_function_pp::invoke; 
     params=this; 
    }  
    private: 
    std::function<double(double)> _func; 
    static double invoke(double x, void *params) { 
    return static_cast<gsl_function_pp*>(params)->_func(x); 
    } 
}; 

तो फिर तुम std :: बाँध का प्रयोग कर एक std :: समारोह में सदस्य समारोह रैप करने के लिए कर सकते हैं। उदाहरण:

gsl_function_pp Fp(std::bind(&Class::member_function, &(*this), std::placeholders::_1)); 
gsl_function *F = static_cast<gsl_function*>(&Fp);  

हालांकि, अगर आप std :: समारोह के प्रदर्शन दंड GSL एकीकरण दिनचर्या के अंदर सदस्य कार्यों लपेटकर से पहले के बारे में पता होना चाहिए। template vs std::function देखें।इस प्रदर्शन को हिट (जो या आप के लिए महत्वपूर्ण नहीं हो सकता है हो सकता है) से बचने के लिए, आप एक सदस्य समारोह की जरूरत निम्नलिखित

Class* ptr2 = this; 
auto ptr = [=](double x)->double{return ptr2->foo(x);}; 
gsl_function_pp<decltype(ptr)> Fp(ptr);  
gsl_function *F = static_cast<gsl_function*>(&Fp); 
कॉल करने के लिए नीचे के रूप में

template< typename F > 
    class gsl_function_pp : public gsl_function { 
    public: 
    gsl_function_pp(const F& func) : _func(func) { 
    function = &gsl_function_pp::invoke; 
    params=this; 
    } 
    private: 
    const F& _func; 
    static double invoke(double x, void *params) { 
    return static_cast<gsl_function_pp*>(params)->_func(x); 
    } 
}; 

से पता चला इस मामले में टेम्पलेट्स का उपयोग करना चाहिए,

पीएस: लिंक template vs std::function बताता है कि कंपाइलर आमतौर पर std :: function की तुलना में टेम्पलेट को अनुकूलित करने में आसान समय होता है (यदि आपका कोड भारी संख्यात्मक गणना कर रहा है तो प्रदर्शन के लिए महत्वपूर्ण है)। तो दूसरे उदाहरण में कामकाज भी कठिन है, यह अधिक बोझिल लगता है, मैं std :: function से टेम्पलेट पसंद करूंगा।

+0

यह एक अच्छा समाधान है लेकिन यह अभी भी स्थिर सदस्य कार्यों का उपयोग करता है। वैसे भी, मैं इसे बंद करने के उत्तर के रूप में चिह्नित करता हूं। मैं जीएसएल से दूर चला गया और अब odeint का उपयोग करें तो मैंने इसका परीक्षण नहीं किया। –

0

आप इस मामले में स्थिर कार्य के बारे में चिंतित क्यों हैं? एक स्थैतिक फ़ंक्शन में घोषित चर और/या ऑब्जेक्ट्स को अलग-अलग धागे के बीच साझा नहीं किया जाता है जब तक वे स्थिर नहीं होते (जो आपके मामले में नहीं होते हैं)।

क्या आपका कोड कुछ करने में विफल रहा है?

+0

अभी नहीं, लेकिन यह एक बड़ा कोड का हिस्सा है जिसे मैं विस्तार करना जारी रखूंगा। मैं अभी के लिए स्थिर का उपयोग कर रहा हूं लेकिन मेरे पास एक गैर स्थैतिक समाधान होगा। एक और लाभ मेरे पूर्ण कोड में 'बाइंड' और 'फ़ंक्शन' –

0

क्षमा करें, लेकिन आप जो करने की कोशिश कर रहे हैं वह कोई समझ नहीं आता है। जो थ्रेड सुरक्षा समस्याएं आप चिंतित हैं, उन्हें static कीवर्ड जोड़कर या हटाकर हल नहीं किया जाएगा।

एकमात्र कारण है कि आप g गैर स्थैतिक क्यों करेंगे यदि के ऑपरेशन के लिए A का कोई उदाहरण आवश्यक था। और जी के वर्तमान कार्यान्वयन के लिए इस तरह के एक उदाहरण की आवश्यकता नहीं है।

नोट static कीवर्ड के बिना, आप g वैश्विक फ़ंक्शन भी बना सकते हैं। आपके मामले में कोई अंतर नहीं होगा। हालांकि यह आपके मामले में g कक्षा में बेहतर शैली है जो इसे स्थिर कार्य के रूप में उपयोग करता है।

इसके अलावा, Here पॉइंटर्स (स्थिर/गैर स्थैतिक) सदस्य कार्यों के बारे में कुछ संबंधित सामग्री है।

+0

को समझना होगा,' g' फ़ंक्शन 'std :: function' सदस्य पर निर्भर करता है। अगर मैं स्थिर सदस्य समारोह में जी स्थिर 'सदस्य का अमान्य उपयोग ... बना देता हूं तो मुझे एक त्रुटि मिलती है। तो मुझे उस 'std :: function' static को बनाना होगा, लेकिन फिर मुझे किसी अन्य वर्ग से फ़ंक्शन निर्दिष्ट करने में कोई समस्या है। –

1

जीएसएल सी ++ के बजाय सी-प्रकार के कार्यों “int (*)(char,float)” लेता है - “int (Fred::*)(char,float)” टाइप करें। किसी सदस्य फ़ंक्शन को सी-प्रकार फ़ंक्शन में कनवर्ट करने के लिए, आपको static जोड़ने की आवश्यकता है।

Is the type of “pointer-to-member-function” different from “pointer-to-function”?