2012-05-23 19 views
16

मैं डिफ़ॉल्ट फ़ंक्शन निर्दिष्ट किए बिना डिफ़ॉल्ट तर्क लेने वाले फ़ंक्शन से कैसे जुड़ सकता हूं और फिर बिना किसी तर्क के इसे कॉल कर सकता हूं?क्या मैं ऐसे फ़ंक्शन से जुड़ सकता हूं जो डिफ़ॉल्ट तर्क लेता है और फिर उसे कॉल करता है?

void foo(int a, int b = 23) { 
    std::cout << a << " " << b << std::endl; 
} 

int main() { 
    auto f = std::bind(foo, 23, 34); // works 
    f(); 


    auto g = std::bind(foo, 23); // doesn't work 
    g(); 

    using std::placeholders::_1; 
    auto h = std::bind(foo, 23, _1); // doesn't work either 
    h(); 

} 
+1

परिभाषित करें "काम नहीं करता"। अगर आप चर के लिए अलग-अलग नाम देते हैं तो कोड संकलित होगा। –

+0

आप एफ को पुन: असाइन क्यों करते रहते हैं? – 111111

+0

@ आर। मार्टिन्होफर्नैंड्स हाँ क्षमा करें, उदाहरण अपूर्ण था। अद्यतन कोड – inf

उत्तर

20

मूल रूप से, किसी भी समय आप foo(x) लिखने संकलक यह foo(x, 23); करने के लिए अनुवाद। यह केवल तभी काम करता है जब आपके पास वास्तव में फ़ंक्शन नाम के साथ सीधे कॉल हो। उदाहरण के लिए, आप &foo को void(*)(int) पर असाइन नहीं कर सकते हैं, क्योंकि फ़ंक्शन का हस्ताक्षर void(int, int) है। डिफ़ॉल्ट पैरामीटर हस्ताक्षर में कोई हिस्सा नहीं खेलते हैं। और यदि आप इसे void(*)(int, int) चर पर असाइन करते हैं, तो डिफ़ॉल्ट पैरामीटर के बारे में जानकारी खो जाती है: आप उस चर के माध्यम से डिफ़ॉल्ट पैरामीटर का लाभ नहीं उठा सकते हैं। std::bind अपने आंतों में कहीं void(*)(int, int) स्टोर करता है, और इस प्रकार डिफ़ॉल्ट पैरामीटर जानकारी खो देता है।

फ़ंक्शन के बाहर से पैरामीटर का डिफ़ॉल्ट मान प्राप्त करने के लिए सी ++ में कोई रास्ता नहीं है, इसलिए जब आप बाध्य करते हैं तो मैन्युअल रूप से डिफ़ॉल्ट मान प्रदान करने के साथ अटक जाते हैं।

+0

महान पृष्ठभूमि, धन्यवाद। – inf

8

मुझे लगता है कि आप एक लैम्ब्डा का उपयोग कर अपने व्यवहार को अनुकरण कर सकते हैं।

auto g = [](){ foo(23); }; 

संपादित करें:

इस की तर्ज पर कुछ बस जाँच की, और ठीक से काम करने लगता है: http://ideone.com/SPSvi

0

मैं दो समाधान है:

1 - आप foo ओवरलोड कर सकते हैं () और इसे डिफ़ॉल्ट के साथ मूल कहते हैं:

void foo(int a, int b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

inline void foo(int a) 
{ 
    foo(a, 23); 
} 

2 - आप डिफ़ॉल्ट के रूप में एक स्थिर चर का उपयोग कर सकते हैं और फिर बाध्यकारी प्रक्रिया में इसका इस्तेमाल करते हैं: आर Martinho फर्नांडीस 'जवाब के साथ

static int foo_default_b = 23; 
void foo(int a, int b = foo_default_b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

auto g = std::bind(foo, 23, foo_default_b); 
g(); 
0

This answer असहमत। आप वास्तव में boost::bind उपयोग कर सकते हैं डिफ़ॉल्ट पैरामीटर के लिए बाध्य करने के लिए, आप बस में प्लेसहोल्डर डाल करने के लिए, तो के रूप में की जरूरत है:

boost::bind<void (int, int)>(foo, _1, _2)(12); 

यह foo(12, 23) फोन करेगा, अपेक्षा के अनुरूप। हालांकि मैंने इस विशिष्ट कोड का परीक्षण नहीं किया है, मैंने ऊपर दिए गए उत्तर के आधार पर अपने कोड में कुछ ऐसा किया है, और यह gcc 4.8.5 में काम करता है।

हम्म, मैंने अभी देखा है कि यह std::bind, boost::bind पर नहीं पूछ रहा है। मुझे नहीं पता कि क्या अंतर है, यदि कोई हो।

संबंधित मुद्दे

 संबंधित मुद्दे