2009-05-05 16 views
5

के साथ अस्वीकार करता है मैं सी ++ में फ़ैक्टर के साथ खेल रहा हूं। विशेष रूप से, मुझे जोड़ों का एक वेक्टर मिला है जो मैं जोड़ी के पहले तत्व द्वारा क्रमबद्ध करना चाहता हूं। मैंने एक पूरी तरह से विशेष मज़ेदार लिखना शुरू कर दिया (यानी कुछ "जैसे बूल माईलेशन (माईपैयर & एलएचएस, माईपैयर & आरएएस)")। फिर, सिर्फ इसलिए कि इस तरह की चीजें दिलचस्प है, मैं एक सामान्य "इस जोड़ी के पहले तत्वों में एफ लागू करें" मज़ेदार लिखने की कोशिश करना चाहता था। मैंने नीचे लिखा है, लेकिन जी ++ इसे पसंद नहीं करता है। मैं:जी ++ मेरे साधारण मज़ेदार को "अपेक्षित एक प्रकार, मिला 'xyz'"

त्रुटि: 'टेम्पलेट struct Pair1stFunc2' त्रुटि के लिए टेम्पलेट पैरामीटर सूची में तर्क 2 में टाइप/मूल्य बेमेल: एक प्रकार की उम्मीद, 'कम'

#include <algorithm> 
#include <functional> 
#include <utility> 
#include <vector> 

template <class P, class F> 
struct Pair1stFunc2 
{ 
    typename F::result_type operator()(P &lhs, P &rhs) const 
    { return F(lhs.first, rhs.first); } 

    typename F::result_type operator()(const P &lhs, const P &rhs) const 
    { return F(lhs.first, rhs.first); } 
}; 

typedef std::pair<int,int> MyPair; 
typedef std::vector<MyPair> MyPairList; 

MyPairList pairs; 

void foo(void) 
{ 
    std::sort(pairs.begin(), 
       pairs.end(), 
       Pair1stFunc2<MyPair, std::less>()); 
} 

किसी को भी किसी भी प्रकाश पर डाला जा सकता है मिल गया मैं यहाँ क्या गलत कर रहा हूँ? मुझे पता है कि यह थोड़ा कृत्रिम उदाहरण है, लेकिन मैं जानना चाहता हूं कि क्या हो रहा है, अगर केवल मेरे एसटीएल-फू को बेहतर बनाने के लिए।

+2

एक बार जब आप इस समस्या को हल कर लेंगे, तो आपके पास दूसरा होगा क्योंकि एफ एक प्रकार है। आप lhs.first और rhs.first का उपयोग कर एक नया एफ बना रहे हैं। आप पाएंगे कि std :: कम में दो-तर्क कन्स्ट्रक्टर नहीं है। आपको एफ * –

+0

प्रकार का * वैल्यू * होना चाहिए, यहां कुछ बढ़ावा देने के लिए कुछ है :: bind-fu: sort (p.begin(), p.end(), बाइंड (कम (), बाइंड (और माईपैयर: : पहला, _1), बांधें (और MyPair :: पहला, _2))); ;) http://codepad.org/NouR5fko –

उत्तर

2

आपको तुलनात्मक प्रकार के साथ std :: कम करने की आवश्यकता है।

Pair1stFunc2<MyPair, std::less<int> >() 

चाल करेगा। अपने ऑपरेटर के भीतर() आपको तुलनात्मक प्रकार की ऑब्जेक्ट को तुरंत चालू करने की आवश्यकता होगी, क्योंकि आप सीधे कक्षा को कॉल नहीं कर सकते हैं। जैसे बदल

return F(lhs.first, rhs.first); 

F func; 
return func(lhs.first, rhs.first); 

को तुम भी functor में विशेषज्ञता के लिए कदम सकता है, के रूप में एक और उत्तर पता चलता है।

+0

वह वास्तव में MyPair के साथ std :: कम का उपयोग नहीं कर रहा है, लेकिन std :: इसके बजाय कम है। –

+0

टेम्पलेट पैरामीटर के रूप में गैर-निर्दिष्ट टेम्पलेट्स के लिए मेरे भाग – Nik

3

ध्यान दें कि std::less स्वयं एक टेम्पलेट है और जब आप इसे foo() फ़ंक्शन के sort से कॉल करते हैं तो आप टेम्पलेट टेम्पलेट पैरामीटर निर्दिष्ट नहीं करते हैं! यहां less एक अपूर्ण प्रकार है और इसलिए समस्या है।

6

dirkgently के जवाब पर विस्तार करने के लिए यहां काम हो सकता है क्या के रूप में आप चाहते हैं का एक उदाहरण है:

template <typename T, template <typename> class F> 
struct Pair1stFunc2 
{ 
    template <typename P> 
    typename F<T>::result_type operator()(P &lhs, P &rhs) const 
    { F<T> f; return f(lhs.first, rhs.first); } 

    template <typename P> 
    typename F<T>::result_type operator()(const P &lhs, const P &rhs) const 
    { F<T> f; return f(lhs.first, rhs.first); } 
}; 

void foo(void) 
{ 
    std::sort(pairs.begin(), 
       pairs.end(), 
       Pair1stFunc2<int, std::less>()); 
} 

ध्यान दें कि यह काम करता है, लेकिन यह वास्तव में क्या आप मन में था नहीं हो सकता है।

template<typename P, bool (*F)(P,P)> struct Pair1stFunc2 { ... } 

इस मामले में, दूसरा तर्क के रूप में एक समारोह टेम्पलेट गुजर अधिभार संकल्प का कारण होगा:

+2

http://codepad.org/54PXQSoL –

+0

+1 पर सही दाएं, मस्तिष्क त्रुटि। – mmmmmmmm

+0

यह काम करता है, लेकिन टेम्पलेट टेम्पलेट पैरामीटर वास्तव में यहां अनावश्यक हैं क्योंकि आप केवल एफ को "एफ " के रूप में संदर्भित करते हैं - मार्टिन यॉर्क के उत्तर को देखें, जो गैर-टेम्पलेटेड तुलनाकर्ताओं के लिए भी काम करेगा। –

1

सरल समाधान के राज्य के लिए एक तर्क, एक उपयुक्त हस्ताक्षर के साथ एक समारोह के रूप में आप क्या चाहते हो जाएगा पी, पी के साथ तर्क प्रकार के रूप में किया। यह काम करता है क्योंकि आप में से अधिभार संकल्प ले जाने struct Pair1stFunc2::operator()

तुम भी एक functor में उत्तीर्ण होने की संभावना चाहते हैं, लेकिन उन एक टेम्पलेट प्रकार तर्क के रूप में पारित होने के लिए और उसके बाद ऑपरेटर() के अंदर बनाई गई की क्या ज़रूरत है:

typename F::result_type operator()(const P &lhs, const P &rhs) const 
{ return F()(lhs.first, rhs.first); } 

यहां, एफ मज़ेदार प्रकार और एफ() उस मज़ेदार का एक उदाहरण है।

तीसरा मामला पहले से ही पहले से ही कवर किया गया है, फ़ैक्टर टेम्पलेट। std :: कम ऐसा टेम्पलेट है। उस स्थिति में, आपको एक टेम्पलेट टेम्पलेट तर्क की आवश्यकता है।

+0

मूल रूप से सही कर सकते हैं, लेकिन मैं कहूंगा कि std :: कम के उदाहरण मज़ेदार हैं। एक मज़ेदार को वाक्यविन्यास एफ (तर्क-सूची) का उपयोग करके बुलाया जा सकता है। आप std :: को इस तरह कम नहीं कह सकते हैं। – MSalters

+0

(मेरी टिप्पणी हटा दी गई क्योंकि इसे संपादित करने से पहले इसका जवाब दिया गया था) –

+0

क्या आप Pair1stFunc2 :: ऑपरेटर() (lhs, rhs) के लिए दो अलग वाक्यविन्यास प्रस्तावित कर रहे हैं, फ़ंक्शन पॉइंटर्स के लिए, दूसरा फ़ैक्टर के लिए? अनुमोदित, फ़ंक्शन पॉइंटर टेम्पलेट पैरामीटर का उपयोग करके आपका समाधान उस मामले के लिए छोटा और तेज़ होना चाहिए, लेकिन आप Pair1stFunc2 को दो टेम्पलेट * टाइप * पैरामीटर (पी और एफ) ले कर एक सिंगल सिंटैक्स का उपयोग कर सकते हैं और एफ के प्रकार एफ को स्टोर कर सकते हैं (यह फ़ंक्शन पॉइंटर केस के लिए 1-Arg ctor में पॉप्युलेट किया जा सकता है)। फिर ऑपरेटर() (एलएचएस, आरएएस) कह सकते हैं "वापसी एफ (lhs.first, rhs.first);"। –

2

अवांछित के समान। लेकिन आपको टेम्पलेट टेम्पलेट्स का उपयोग करने की आवश्यकता नहीं है।

#include <algorithm> 
#include <functional> 
#include <memory> 
#include <vector> 

typedef std::pair<int,int> MyPair; 
typedef std::vector<MyPair> MyPairList; 
MyPairList pairs; 


// Same as original. 
template <typename T,typename F> 
struct Pair1stFunc2 
{ 
    template <typename P> 
    typename F::result_type operator()(P &lhs, P &rhs) const 
    { F f; // Just need to create an anstance of the functor to use. 
     return f(lhs.first, rhs.first); } 

    template <typename P> 
    typename F::result_type operator()(const P &lhs, const P &rhs) const 
    { F f; // Just need to create an anstance of the functor to use. 
     return f(lhs.first, rhs.first); } 
}; 


void foo(void) 
{ 
    std::sort(pairs.begin(), 
       pairs.end(), 
       Pair1stFunc2<int, std::less<int> >()); // initialize the version of less 
} 
+0

+1। यह अवांछित समाधान से अधिक सामान्य है क्योंकि यह गैर-टेम्पलेटेड तुलनित्रों के लिए भी काम करेगा। –

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