2015-02-01 30 views
7

सी ++ 14 के साथ हमें कुछ एसोसिएटिव कंटेनरों (जैसे std :: set) के तत्वों की तुलना किसी अन्य कंटेनर में संग्रहीत किए गए लोगों की तुलना करने की अनुमति है। यह काम करना चाहिए जब तुलनित्र के पास is_transparent एक प्रकार के रूप में दर्शाया गया है (उदाहरण के लिए std::set::find देखें)।मैं is_transparent प्रकार के साथ तुलनित्र का उपयोग कैसे करूं?

मान लीजिए कि मेरे पास एक स्ट्रिंग रैपर है जो स्ट्रिंग पर कुछ चेक करता है (यदि यह प्रारूप मान्य प्रारूप है और इसी तरह - वास्तव में महत्वपूर्ण नहीं है, लेकिन इसे बनाना इतना भारी है कि मैं इससे बचना चाहता हूं + यह फेंक सकता है अपवाद) और यह अद्वितीय मूल्यों का एक कंटेनर रखने के लिए std :: set में संग्रहीत है। मुझे इसके लिए एक तुलनित्र कैसे लिखना चाहिए? क्या यह नीचे की तरह दिखना चाहिए? क्या मैं इसे प्राप्त करने के लिए अपने sw::operator<() का अधिभार और उपयोग कर सकता हूं?

class sw 
{ 
public: 
    explicit sw(const std::string& s) : s_(s) { /* dragons be here */ } 
    const std::string& getString() const { return s_; } 

    bool operator<(const sw& other) const { return s_ < other.s_; } 

private: 
    std::string s_; 
}; 

struct Comparator 
{ 
    using is_transparent = std::true_type; 

    bool operator()(const sw& lhs, const std::string& rhs) const { return lhs.getString() < rhs; } 
    bool operator()(const std::string& lhs, const sw& rhs) const { return lhs < rhs.getString(); } 
    bool operator()(const sw& lhs, const sw& rhs) const { return lhs < rhs; } 
}; 

int main() 
{ 
    std::set<sw, Comparator> swSet{ sw{"A"}, sw{"B"}, sw{"C"} }; 
    std::cout << std::boolalpha << (swSet.find(std::string("A")) != swSet.end()) << std::endl; 
} 

मुझे विश्वास है कि इसके बाद के संस्करण कोड अपेक्षित ढंग से काम करना चाहिए, लेकिन जब मैं जी ++ 4.9 और बजना ++ 3.6 के साथ यह परीक्षण किया है, दोनों key_type करने के लिए string से रूपांतरण लापता के रूप में अगर Comparator::operator() की स्ट्रिंग भार के थे के बारे में त्रुटियों झुकेंगे कभी ध्यान में नहीं लिया। क्या मैं कुछ भूल रहा हूँ?

+4

कि libstdc संस्करण ++ (जीसीसी की मानक लाइब्रेरी) जो जी ++ 4.9 के साथ आता है, ने विषम लुकअप को लागू नहीं किया है। आपका कोड [क्लैंग और libC++] के साथ ठीक संकलित करता है (http://coliru.stacked-crooked.com/a/97c0421099d7912d)। –

+0

@ टी.सी. .: धन्यवाद, यह समझ में आता है और यही वह है जिसे मैं डरता था ... मैंने इसे क्लैंग और -stdlib = libC++ के साथ करने की कोशिश की और यह इरादे के रूप में काम किया। बहुत बुरा है कि मेरा डिफ़ॉल्ट वातावरण g ++ और libstdC++ है। –

+4

इसे दो सप्ताह से भी कम समय में https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=219888 में कार्यान्वित किया गया है। –

उत्तर

3

हां, यह कोड सही है, लेकिन यह operator< ओवरलोड std::string के साथ अपने प्रकार की तुलना की अनुमति के लिए आसान हो जाएगा और फिर बस std::less<> (अर्थात std::less<void>) का उपयोग जो "पारदर्शी" पहले से ही है।

inline bool operator<(const sw& lhs, const std::string& rhs) { return lhs.getString() < rhs; } 
inline bool operator<(const std::string& lhs, const sw& rhs) { return lhs < rhs.getString(); } 

std::set<sw, std::less<>> swSet{ sw{"A"}, sw{"B"}, sw{"C"} }; 

इसके अलावा, यह संभवतः ध्यान देने योग्य है कि यह कोई फर्क नहीं पड़ता है कि तुम क्या is_transparent परिभाषित करने के लिए, इनमें से किसी में यह की अपनी परिभाषा के रूप में एक ही प्रभाव होगा:

using is_transparent = std::false_type; 

using is_transparent = void; 
+0

हू, मुझे 'कम ' और उसके व्यवहार के बारे में पता नहीं था, यह अच्छा है। फिर भी, जब इस तरह की चीजें करते हैं, तो मुझे एक अलग तुलनित्र क्लीनर और अधिक अभिव्यक्ति मिलती है, लेकिन शायद यह एक व्यक्तिगत वरीयता है। :) –

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