আমার ক্লাসের জন্য কীভাবে অদলবদল করা যায়?


89

আমার swapএসটিএল অ্যালগরিদমে সক্ষম করার উপযুক্ত উপায় কী ?

1) সদস্য swap। নেই std::swapসদস্য ব্যবহার করতে SFINAE কৌতুক ব্যবহার swap

2) swapএকই নাম স্থানে নিখরচায় অবস্থান ।

3) আংশিক বিশেষায়িতকরণ std::swap

4) উপরের সব।

ধন্যবাদ.

সম্পাদনা: দেখে মনে হচ্ছে আমি আমার প্রশ্নটি পরিষ্কার করে বলি নি। মূলত, আমার একটি টেম্পলেট ক্লাস রয়েছে এবং সেই শ্রেণীর জন্য আমার লেখা (দক্ষ) অদলবদল পদ্ধতিটি ব্যবহার করার জন্য আমার এসটিএল অ্যালগোস প্রয়োজন।

উত্তর:


95
  1. সঠিক ব্যবহার এর swap। আপনি যখন "লাইব্রেরি" কোডটি লেখেন এবং এডিএল (তর্ক-নির্ভর উপর নির্ভরশীল) সক্ষম করতে চান তখন এইভাবে লিখুন 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আপনার শ্রেণীর জন্য কোনও ফাংশন সরবরাহ করার উপযুক্ত উপায় Is
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
ডেনিস জিকিফুজ

4
@ শিও। আপনার ইনপুট জন্য ধন্যবাদ। আমি আমার প্রশ্ন সম্পাদনা করেছি। আপনি যেমন 1 এর ক্ষেত্রে বর্ণনা করেছেন তেমন কি এসটিএলও অদলবদল ব্যবহার করে?
পিক

4
@ পিক: হ্যাঁ, এসটিএল 1 এ দেখানো এডিএল স্বাপটি ব্যবহার করবে) তবে কেবল এটি কোনও সদস্য ফাংশন নয়, যদি এটি কোনও ফ্রি ফাংশন হিসাবে উপস্থিত থাকে তবেই। 2) এবং 3 দেখুন), উভয় সংস্করণ অ্যালগরিদম দ্বারা বাছাই করা হবে। আমি পরামর্শ 2), হিসাবে 3) পুরানো এবং খারাপ অভ্যাস হিসাবে বিবেচিত।
Xeo

4
কোডটির প্রথম অংশে করা মন্তব্যটি বিভ্রান্তিকর। using std::swap;ADL সক্ষম করে না, এটি std::swapADL একটি সঠিক ওভারলোড খুঁজে না পাওয়া মাত্র সংকলকটি সনাক্ত করতে দেয় ।
ডেভিড রদ্রিগেজ - ড্রিবিস

6
এই উত্তরটি টেকনিক্যালি সঠিক, কিন্তু দারুণভাবে স্বচ্ছতার জন্য সম্পাদনা প্রয়োজন। ওপি'র (1) সঠিক উত্তর নয় কারণ এই উত্তরে অতিরিক্ত মাত্রায় পড়া ভুল করে বোঝা যাচ্ছে।
হাওয়ার্ড হিনান্ট

1

EDIT- র উত্তর দেওয়ার জন্য, যেখানে ক্লাসগুলি টেম্পলেট শ্রেণি হতে পারে, আপনার কোনও বিশেষীকরণের প্রয়োজন নেই। এর মতো একটি শ্রেণী বিবেচনা করুন:

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

আপনি ক্লাস সংজ্ঞায়িত করতে পারেন যেমন:

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

আপনি যদি সমস্ত 3 টি অদলবদল বাস্তবায়নের জন্য একটি ফাংশন তৈরি করতে সক্ষম হতে চান (এই উদাহরণ শ্রেণীর পক্ষ থেকে এটি পরোয়ানা দেয় না) আপনি যেমন শিও (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

দেখে মনে হচ্ছে (২) ( ব্যবহারকারী-সংজ্ঞায়িত শ্রেণীর ঘোষণা করা একই নামস্থানে অবাধ স্থায়ী অবস্থানswap ) ব্যবহারকারী-সংজ্ঞায়িত শ্রেণীর জন্য একমাত্র অনুমোদিত উপায় swap, কারণ নামস্থানে ঘোষণাগুলি যুক্ত stdকরা সাধারণত একটি অপরিজ্ঞাত আচরণ। নেমস্পেস স্ট্যান্ড (সিপ্রেফারেন্স ডটকম) প্রসারিত করা :

নীচে উল্লিখিত কয়েকটি ব্যতিক্রম ব্যতীত নেমস্পেসে stdবা কোনও নেমস্পেসের মধ্যে নামকরণে ঘোষণা বা সংজ্ঞা যুক্ত করা অপরিজ্ঞাত আচরণ isstd

এবং swapএই ব্যতিক্রমগুলির মধ্যে একটি হিসাবে চিহ্নিত করা হয় না। সুতরাং নিজের swapজায়গার নিজের stdনাম বোঝাতে যুক্ত করা একটি অপরিজ্ঞাত আচরণ।

এটি আরও বলা হয় যে স্ট্যান্ডার্ড লাইব্রেরি যদি কোনও ব্যবহারকারী শ্রেণীর জন্য swapব্যবহারকারী-সংজ্ঞায়িত কল করার জন্য ফাংশনে একটি অযোগ্য কল ব্যবহার করে swapতবে যদি এই জাতীয় ব্যবহারকারীর সংজ্ঞা swapদেওয়া থাকে।

অদলবদল (cppreferences.com) :

অনেক মান গ্রন্থাগার ফাংশন (উদাহরণস্বরূপ, অনেক আলগোরিদিম) সন্তুষ্ট তাদের আর্গুমেন্ট আশা Swappable , যার মানে যে কোন সময় মান গ্রন্থাগার সঞ্চালিত একটি swap, এটা সমতুল্য ব্যবহার using std::swap; swap(t, u);

অদলবদল (www.cplusplus.com) :

মান লাইব্রেরী (মধ্যে বহু উপাদান std) কলের swapএকটি ইন অযোগ্য কাস্টম overloads: পদ্ধতিতে অ মৌলিক ধরনের জন্য কাস্টম overloads এই জেনেরিক সংস্করণের পরিবর্তে বলা যেতে অনুমতি দিতে 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.
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.