2012-03-15 11 views
5

का उपयोग करके तर्क कैसे गुजर रहा है मुझे पता चलेगा कि std :: mem_fun का उपयोग करके तर्क पारित करने का कोई तरीका है या नहीं? मैं सटीक बनाना चाहता हूं कि मेरे पास जितना संभव हो उतना तर्क हो सकता है और बहुत से सदस्य कार्य हो सकते हैं।
समस्या यह है कि मैं एक पुराने मानक पर हूं और मैं एक पूर्ण एसएलएल रास्ता तलाश रहा हूं इसलिए अगर मुझे पता है कि मैं इसे आसानी से कर सकता हूं तो भी बढ़ावा देने की अनुमति नहीं है =/std :: mem_fun

यहां थोड़ा सा है मैं कैसे करना चाहते हैं के चित्रण के लिए इसका इस्तेमाल:

#include <list> 
#include <algorithm> 

// Class declaration 
// 
struct Interface { 
    virtual void run() = 0; 
    virtual void do_something(int) = 0; 
    virtual void do_func(int, int) = 0; 
}; 

struct A : public Interface { 
    void run() { cout << "Class A : run" << endl; } 
    void do_something(int foo) { cout << "Class A : " << foo << endl; } 
    void do_func(int foo, int bar) { cout << "Class A : " << foo << " " << bar << endl; } 
}; 

struct B : public Interface { 
    void run() { cout << "Class B : run" << endl; } 
    void do_something(int foo) { cout << "Class B : " << foo << endl; } 
    void do_func(int foo, int bar) { cout << "Class B : " << foo << " " << bar << endl; } 
}; 

// Main 
// 
int main() { 
    // Create A and B 
    A a; 
    B b; 

    // Insert it inside a list 
    std::list<Interface *> list; 
    list.push_back(&a); 
    list.push_back(&b); 

    // This works 
    std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::run)); 

    // But how to give arguments for those member funcs ? 
    std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::do_something)); 
    std::for_each(list.begin(), list.end(), std::mem_fun(&Interface::do_func)); 
    return 0; 
} 

उत्तर

11

std::bind1st के माध्यम से उपयोग std::bind और std::bind2nd

std::for_each(list.begin(), list.end(), 
       std::bind2nd(std::mem_fun(&Interface::do_something),1) // because 1st is this 
      ); 

दुर्भाग्य से, मानक दो तर्क संस्करण के लिए मदद नहीं करता है और आप अपने खुद के बारे में की जरूरत है:

struct MyFunctor 
{ 
    void (Interface::*func)(int,int); 
    int   a; 
    int   b; 

    MyFunctor(void (Interface::*f)(int,int), int a, int b): func(f), a(a), b(b) {} 

    void operator()(Interface* i){ (i->*func)(a,b);} 
}; 

std::for_each(list.begin(), list.end(), 
       MyFunctor(&Interface::do_func, 1, 2) 
      ); 
1

std::bind1st और std::bind2nd देखें। वे उपयोग करने के लिए काफी बेवकूफ और बदसूरत हैं, लेकिन यदि आप केवल बिना किसी जोड़ के सी ++ 03 में मौजूद चीज़ों का उपयोग करने का आग्रह करते हैं, तो वे सब कुछ उपलब्ध हैं।

संपादित करें: कब/अगर मुझे ऐसा करने की ज़रूरत है, तो मैं आमतौर पर std::bind1st और/या std::bind2nd का उपयोग करने के बजाय इसे एक छोटे से मज़ेदार वर्ग के साथ करता हूं। यह अंततः उन उत्पन्न करने वालों से बहुत अलग नहीं है, लेकिन (आईएमओ) यह आम तौर पर अधिक पठनीय है।

template<class T> 
class invoke_do_something { 
    int value; 
public: 
    adder(int x) : value(x) {} 
    void operator()(T &t) { 
     t.do_something(value); 
    } 
}; 

std::for_each(list.begin(), list.end(), invoke_do_something(1)); 

मेरा स्वयं का लेना यह है कि ज्यादातर समय यह बैंड-एड्स की तरह है। यह लगातार for_each का उपयोग होता है। मुझे आमतौर पर लगता है कि कुछ विचारों के साथ, मुझे एक अधिक उपयुक्त एल्गोरिदम मिल सकता है, जो अक्सर इस आदेश पर किसी भी चीज की आवश्यकता को समाप्त करता है।

+0

उत्तर के लिए धन्यवाद, क्या आप इसका उदाहरण दे सकते हैं इसका इस्तेमाल कैसे करें ? मैं इसे काम नहीं कर सकता .. – klefevre

+0

मुझे लगता है कि मैं कर सकता था, लेकिन 1) @ लोकी एस्टारी पहले से ही है, इसलिए इसमें ज्यादा वृद्धि नहीं होगी, और 2) मैंने कभी उनका उपयोग नहीं किया। मैंने बहुत समय पहले फैसला किया कि वे परेशानी के लायक नहीं थे। (आश्चर्यजनक रूप से दुर्लभ) स्थिति में जहां मुझे उस तरह की चीज की ज़रूरत है, मैं इससे निपटने के लिए एक छोटी मजेदार कक्षा लिखता हूं। शुक्र है, सी ++ 11 में, इसे भी खत्म करना आसान है। –

+0

वैसे भी धन्यवाद .. – klefevre

1

आप कर सकते हैं जुड़ कर:

using std::placeholders::_1 
int a; 
std::for_each(list.begin(), list.end(), std::bind(&Interface::do_something, _1, a)); 
+2

वह "पुराना मानक" है, यानी 98 या 03. यह सी ++ 11 है। – MSalters

+0

@MSalters: ध्यान दिया कि, हालांकि, सी ++ 11 पिछले साल sooooo है। –

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