'टपल' और 'टाई' के माध्यम से तुलना ऑपरेटरों को लागू करना, एक अच्छा विचार है?


98

(ध्यान दें: tupleऔर tieबूस्ट या सी ++ 11 से लिया जा सकता है।)
केवल दो तत्वों के साथ छोटी संरचनाएं लिखते समय, मैं कभी-कभी एक का चयन करता हूं std::pair, क्योंकि उस डेटाटाइप के लिए सभी महत्वपूर्ण सामान पहले से ही किया जाता है, जैसे कि operator<सख्त-कमजोर-ऑर्डर करना ।
हालांकि downsides बहुत बेकार चर नाम हैं। यहां तक ​​कि अगर मैंने खुद को बनाया है typedef, तो मुझे 2 दिन बाद याद नहीं होगा firstकि secondवास्तव में क्या और क्या था, खासकर अगर वे दोनों एक ही प्रकार के हैं। यह दो से अधिक सदस्यों के लिए और भी बदतर हो जाता है, क्योंकि घोंसले के शिकार pairबहुत ज्यादा बेकार है।
उसके लिए अन्य विकल्प एक हैtupleया तो बूस्ट या सी ++ 11 से, लेकिन यह वास्तव में किसी भी अच्छे और स्पष्ट नहीं दिखता है। इसलिए मैं किसी भी आवश्यक तुलना संचालकों सहित, स्वयं संरचना लिखने के लिए वापस जाता हूं।
चूंकि विशेष रूप से operator<काफी बोझिल हो सकता है, मैंने इस पूरी गड़बड़ी को रोकने के बारे में सोचा था कि केवल इसके लिए परिभाषित संचालन पर निर्भर होकर tuple:

उदाहरण के लिए operator<, सख्त-कमजोर-आदेश के लिए उदाहरण:

bool operator<(MyStruct const& lhs, MyStruct const& rhs){
  return std::tie(lhs.one_member, lhs.another, lhs.yet_more) <
         std::tie(rhs.one_member, rhs.another, rhs.yet_more);
}

( tieएक बनाता है tupleके T&पारित कर दिया तर्कों से संदर्भ।)


संपादित करें : @DeadMG से निजी तौर पर विरासत में लेने tupleका सुझाव बुरा नहीं है, लेकिन इसमें कुछ कमियां हैं:

  • यदि ऑपरेटर स्वतंत्र हैं (संभवतः मित्र), तो मुझे सार्वजनिक रूप से विरासत में प्राप्त करने की आवश्यकता है
  • कास्टिंग के साथ, मेरे कार्यों / ऑपरेटरों ( operator=विशेष रूप से) को आसानी से बायपास किया जा सकता है
  • tieसमाधान के साथ , मैं कुछ सदस्यों को छोड़ सकता हूं यदि वे आदेश देने के लिए कोई मायने नहीं रखते हैं

क्या इस कार्यान्वयन में कोई कमियां हैं जिन पर मुझे विचार करने की आवश्यकता है?


1
मुझे पूरी तरह से उचित लगता है ...
iljarn

1
यह एक बहुत ही चालाक विचार है, भले ही वह पैन न करे। मैं इसकी जांच करने जा रहा हूं।
टेम्प्लेटेटपेडिफ

यह बहुत उचित लगता है। अब मैं केवल यही सोच सकता हूं कि tieबिट-फील्ड सदस्यों पर लागू नहीं किया जा सकता है।
इस्ट विस्टरिया

4
मुझे यह विचार पसंद है! यदि tie(...)कॉल विभिन्न ऑपरेटरों (=, ==, <, आदि) में डुप्लिकेट होने जा रहे हैं, तो आप एक निजी इनलाइन विधि लिख सकते हैं make_tuple(...)कि वे इनकैप्सुलेट करें और फिर विभिन्न अन्य स्थानों से कॉल करें, जैसे कि return lhs.make_tuple() < rhs.make_tuple();(हालांकि वापसी प्रकार से) इस विधि को घोषित करने के लिए मजेदार हो सकता है!)
'16

13
@aldo: बचाव के लिए C ++ 14! auto tied() const{ return std::tie(the, members, here); }
Xio

जवाबों:


60

यह निश्चित रूप से इसे सही रोल करने की तुलना में एक सही ऑपरेटर लिखना आसान बनाने जा रहा है। मैं कहूंगा कि केवल एक अलग दृष्टिकोण पर विचार करें यदि प्रोफाइलिंग तुलना ऑपरेशन को आपके आवेदन का समय लेने वाला हिस्सा दिखाता है। अन्यथा इसे बनाए रखने में आसानी किसी भी संभावित प्रदर्शन चिंताओं से आगे बढ़ना चाहिए।


17
मैं एक मामले में जहां कल्पना नहीं कर सकते tuple<>की operator<एक हस्तलिखित एक से किसी भी धीमी होगी।
िलालजर्न

51
मुझे यह एक ही विचार एक बार मिला, और कुछ प्रयोग किया। यह देखकर आश्चर्यचकित था कि कंपाइलर ने इनबिल्ट और ऑप्टिमाइज़ किया और सब कुछ ट्यूपल्स और रेफरेंस के साथ किया, असेंबली को हाथ से लिखे कोड के समान फेंक दिया।
JohannesD


क्या यह सख्त कमजोर आदेश की गारंटी देता है ? कैसे?
CinCout

5

मैं इसी समस्या को लेकर आया हूं और मेरा समाधान c ++ 11 वैरेडिक टेम्प्लेट का उपयोग करता है। यहाँ कोड आता है:

.H हिस्सा:

/***
 * Generic lexicographical less than comparator written with variadic templates
 * Usage:
 *   pass a list of arguments with the same type pair-wise, for intance
 *   lexiLessthan(3, 4, true, false, "hello", "world");
 */
bool lexiLessthan();

template<typename T, typename... Args>
bool lexiLessthan(const T &first, const T &second, Args... rest)
{
  if (first != second)
  {
    return first < second;
  }
  else
  {
    return lexiLessthan(rest...);
  }
}

और बिना बहस के आधार मामले के लिए .cpp:

bool lexiLessthan()
{
  return false;
}

अब आपका उदाहरण बनता है:

return lexiLessthan(
    lhs.one_member, rhs.one_member, 
    lhs.another, rhs.another, 
    lhs.yet_more, rhs.yet_more
);

मैं यहाँ इसी तरह के समाधान में डाल दिया, लेकिन आवश्यकता नहीं है! = ऑपरेटर। stackoverflow.com/questions/11312448/…
steviekm3

3

मेरी राय में, आप अभी भी एक ही मुद्दे को हल नहीं कर रहे std::tupleहैं- अर्थात्, आपको यह जानना होगा कि दोनों और प्रत्येक सदस्य चर का नाम कितने हैं, आप इसे फ़ंक्शन में दो बार दोहरा रहे हैं। आप privateवंशानुक्रम का विकल्प चुन सकते हैं ।

struct somestruct : private std::tuple<...> {
    T& GetSomeVariable() { ... }
    // etc
};

यह दृष्टिकोण एक है थोड़ा एक मेस के साथ शुरू की थोड़ा और अधिक, लेकिन आप केवल करने के बजाय हर ऑपरेटर आप अधिभार करना चाहते हैं के लिए हर जगह में एक ही स्थान पर चर और नाम को बनाए रखने रहे हैं।


3
इसलिए मैं नाम एक्सेसर्स जैसे वेरिएबल्स T& one_member(){ return std::get<0>(*this); }आदि का उपयोग कर रहा हूं ? लेकिन क्या मुझे जरूरत नहीं है कि मैं प्रत्येक "सदस्य" के लिए इस तरह की विधि प्रदान करूं, जिसमें कॉन्स्ट और नॉन-कास्ट संस्करण के लिए ओवरलोड शामिल हैं?
Xeo

@ Xeo को वास्तविक वैरिएबल बनाने की तुलना में किसी भी अधिक काम की आवश्यकता के रूप में नामित एक्सेसर्स नहीं दिखते हैं। किसी भी तरह से आपके पास प्रत्येक चर के लिए एक अलग नाम होना चाहिए। मुझे लगता है कि कास्ट / नॉन-कांस्टेंट के लिए दोहराव होगा। हालाँकि, आप इस सभी कार्य को टेम्पलेट कर सकते हैं।
ली लोविरे

1

यदि आप एक से अधिक ऑपरेटर अधिभार, या ट्यूपल से अधिक विधियों का उपयोग करने की योजना बनाते हैं, तो मैं टपल को कक्षा का सदस्य बनाने या टपल से प्राप्त करने की सलाह दूंगा। अन्यथा, आप जो कर रहे हैं वह बहुत अधिक काम है। जब दोनों के बीच तय करने, जवाब देने के लिए एक महत्वपूर्ण सवाल यह है: क्या आप अपने वर्ग के लिए चाहते हो सकता है एक टपल? यदि नहीं, तो मैं प्रतिनिधिमंडल का उपयोग करके एक टपल रखने और इंटरफ़ेस को सीमित करने की सिफारिश करूंगा।

आप टपल के सदस्यों का नाम बदलने के लिए एक्सेसर्स बना सकते हैं।


मैंने ओपी के प्रश्न को इस अर्थ में पढ़ा कि "क्या मेरी कक्षा ' operator<का उपयोग std::tieउचित है?" मुझे समझ नहीं आता कि यह उत्तर उस प्रश्न से कैसे संबंधित है।
20

@ildjarn कुछ टिप्पणियाँ हैं जो मैंने यहाँ पोस्ट नहीं कीं। मैंने सब कुछ संकलित किया है ताकि यह बेहतर ढंग से पढ़े।
ली लोविरे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.