मेरी कक्षा के लिए स्वैप फ़ंक्शन कैसे प्रदान करें?


89

swapएसटीएल एल्गोरिदम में मुझे सक्षम करने का उचित तरीका क्या है ?

1) सदस्य swap। क्या std::swapसदस्य का उपयोग करने के SFINAE चाल का उपयोग swap

2) swapएक ही नामस्थान में मुक्त खड़े ।

3) का आंशिक विशेषज्ञता std::swap

4) उपरोक्त सभी।

धन्यवाद।

संपादित करें: ऐसा लगता है कि मैंने अपना प्रश्न स्पष्ट रूप से नहीं लिखा है। असल में, मेरे पास एक टेम्प्लेट क्लास है और मुझे उस क्लास के लिए लिखी गई (कुशल) स्वैप विधि का उपयोग करने के लिए एसटीएल अल्गोस की आवश्यकता है।

जवाबों:


95
  1. का समुचित उपयोग है swap। इसे इस तरह लिखें जब आप "लाइब्रेरी" कोड लिखते हैं और ADL (तर्क-निर्भर लुकअप) को सक्षम करना चाहते हैं swap। इसके अलावा, इसका SFINAE से कोई लेना-देना नहीं है।
// some algorithm in your code
template<class T>
void foo(T& lhs, T& rhs) {
    using std::swap; // enable 'std::swap' to be found
                    // if no other 'swap' is found through ADL
    // some code ...
    swap(lhs, rhs); // unqualified call, uses ADL and finds a fitting 'swap'
                    // or falls back on 'std::swap'
    // more code ...
}
  1. swapअपनी कक्षा के लिए एक समारोह प्रदान करने का उचित तरीका है ।
namespace Foo {

class Bar{}; // dummy

void swap(Bar& lhs, Bar& rhs) {
    // ...
}

}

यदि swapअब 1 में दिखाया गया है), तो आपका फ़ंक्शन मिल जाएगा। इसके अलावा, आप उस फ़ंक्शन को एक दोस्त बना सकते हैं, यदि आपको पूरी तरह swapसे मुफ्त फ़ंक्शन द्वारा बुलाया जाने वाला एक सदस्य प्रदान करना है या प्रदान करना है:

// version 1
class Bar{
public:
    friend void swap(Bar& lhs, Bar& rhs) {
    // ....
    }
};

// version 2
class Bar{
public:
    void swap(Bar& other) {
    // ...
    }
};

void swap(Bar& lhs, Bar& rhs) {
    lhs.swap(rhs);
}

...
  1. आप एक स्पष्ट विशेषज्ञता का मतलब है। आंशिक अभी भी कुछ और है और कार्यों के लिए भी संभव नहीं है, केवल संरचना / वर्ग। जैसे, जब से तुम विशेषज्ञ नहीं कर सकते std::swapटेम्पलेट वर्गों के लिए, आप है अपने नाम स्थान में एक नि: शुल्क समारोह प्रदान करते हैं। बुरी बात नहीं है, अगर मैं ऐसा कह सकता हूं। अब, एक स्पष्ट विशेषज्ञता भी संभव है, लेकिन आम तौर पर आप एक फ़ंक्शन टेम्पलेट को विशेषज्ञ नहीं बनाना चाहते हैं :
namespace std
{  // only allowed to extend namespace std with specializations

template<> // specialization
void swap<Bar>(Bar& lhs, Bar& rhs) noexcept {
    // ...
}

}
  1. नहीं, जैसा कि 1) 2 से अलग है) और 3)। इसके अलावा, 2) और 3) दोनों को हमेशा 2) उठाया जाएगा, क्योंकि यह बेहतर होगा।

8
आपका (1) और सवाल का (1) वास्तव में लाइन नहीं है, जब तक कि मैं कुछ गलत नहीं कर रहा हूं। फिर भी, +1
डेनिस ज़िकफ़ोज़

1
@Xeo। इनपुट के लिए धन्यवाद। मैंने अपना प्रश्न संपादित किया। क्या एसटीएल स्वैप का उपयोग करता है जैसा कि आपने मामले 1 में वर्णित किया था?
पिक 11

1
: 2) और 3 देखें), दोनों संस्करण एल्गोरिदम द्वारा उठाए जाएंगे। मुझे सलाह है कि 2), 3 के रूप में) आउट-डेटेड है और बुरा व्यवहार माना जाता है।
Xeo

2
कोड के पहले भाग में टिप्पणी भ्रामक है। using std::swap;ADL को सक्षम नहीं करता है, यह केवल संकलक को यह पता लगाने की अनुमति देता है std::swapकि ADL को उचित अधिभार नहीं मिला है।
डेविड रॉड्रिग्ज़ - ड्रिबीज़

6
इस उत्तर तकनीकी रूप से सही है, लेकिन है अत्यंत कष्ट स्पष्टता के लिए संपादन की जरूरत होती। ओपी का (1) सही उत्तर नहीं है क्योंकि इस उत्तर में जल्दी-जल्दी पढ़ने से गलती से संकेत मिलेगा।
हावर्ड हिनेंट

1

EDIT का उत्तर देने के लिए, जहाँ कक्षाएं टेम्पलेट क्लासेस हो सकती हैं, आपको विशेषज्ञता की आवश्यकता नहीं है। इस तरह एक वर्ग पर विचार करें:

template <class T>
struct vec3
{
    T x,y,z;
};

आप इस तरह के रूप में वर्गों को परिभाषित कर सकते हैं:

vec3<float> a;
vec3<double> b;
vec3<int> c;

यदि आप सभी 3 स्वैप को लागू करने के लिए एक फ़ंक्शन बनाने में सक्षम होना चाहते हैं (यह नहीं कि यह उदाहरण वर्ग वारंट है) तो आप ठीक उसी तरह करते हैं जैसे कि Xeo ने कहा (2) ... बिना विशेषज्ञता के लेकिन बस एक नियमित टेम्पलेट फ़ंक्शन करें:

template <class T>
void swap(vec3<T> &a, vec3<T> &b)
{
    using std::swap;
    swap(a.x,b.x);
    swap(a.y,b.y);
    swap(a.z,b.z);
}

स्वैप टेम्पलेट फ़ंक्शन उसी नामस्थान में स्थित होना चाहिए जिस वर्ग को आप स्वैप करने का प्रयास कर रहे हैं। निम्न विधि उस स्वैप को खोजेगी और उपयोग करेगी, भले ही आप ADL का उपयोग करके उस नामस्थान का संदर्भ नहीं दे रहे हों:

using std::swap;
swap(a,b);

0

ऐसा लगता है कि (2) ( उसी नामस्थान में मुक्त होना swapजहां उपयोगकर्ता परिभाषित वर्ग घोषित है ) उपयोगकर्ता-परिभाषित वर्ग के लिए प्रदान करने का एकमात्र अनुमत तरीका है swap, क्योंकि नामस्थान stdमें घोषणाओं को जोड़ना आम तौर पर एक अपरिभाषित व्यवहार है। नाम स्थान std (cppreference.com) का विस्तार :

नीचे उल्लिखित कुछ अपवादों के साथ नामस्थान stdया किसी भी नामस्थान में घोषित या परिभाषाओं को जोड़ने के लिए अपरिभाषित व्यवहार हैstd

और swapउन अपवादों में से एक के रूप में निरूपित नहीं किया जाता है। तो अपने स्वयं के swapअधिभार को stdनेमस्पेस में जोड़ना एक अपरिभाषित व्यवहार है।

यह भी कहा जाता है कि मानक पुस्तकालय swapफ़ंक्शन के लिए एक अयोग्य कॉल का उपयोग करता है ताकि swapउपयोगकर्ता वर्ग के लिए उपयोगकर्ता-परिभाषित कॉल किया जा सके यदि ऐसा उपयोगकर्ता-परिभाषित swapप्रदान किया गया हो।

स्वैपेबल (cppreference.com) :

कई मानक लाइब्रेरी फ़ंक्शंस (उदाहरण के लिए, कई एल्गोरिदम) स्वैपेबल को संतुष्ट करने के लिए उनके तर्क की अपेक्षा करते हैं , जिसका अर्थ है कि किसी भी समय मानक लाइब्रेरी एक स्वैप करता है, इसके बराबर का उपयोग करता है using std::swap; swap(t, u);

स्वैप (www.cplusplus.com) :

मानक लाइब्रेरी के कई घटक (भीतर std) गैर-मौलिक प्रकारों के लिए कस्टम अधिभार की अनुमति देने के लिए swapएक अयोग्य तरीके से कॉल करते हैं जो इस सामान्य संस्करण के बजाय कहे जाते हैं: कस्टम ओवरलोड swapको उसी नामस्थान में घोषित किया जाता है जिस प्रकार के लिए उन्हें चुना जाता है। इस सामान्य संस्करण पर तर्क-निर्भर लुकअप के माध्यम से ।

लेकिन ध्यान दें कि std::swapउपयोगकर्ता-परिभाषित वर्ग के लिए सीधे फ़ंक्शन का उपयोग करना उपयोगकर्ता-परिभाषित के std::swapबजाय सामान्य संस्करण को कॉल करता है swap:

my::object a, b;
std::swap(a, b); // calls std::swap, not my::swap

तो यह swapफ़ंक्शन को उसी तरह से उपयोगकर्ता कोड में कॉल करने की सिफारिश की जाती है, जैसा कि मानक पुस्तकालय में किया जाता है:

my::object a, b;
using std::swap;
swap(a, b); // calls my::swap if it is defined, or std::swap if it is not.
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.