সি ++ ২০ প্রবর্তিত ডিফল্ট তুলনাগুলি, "দ্য স্পেসশিপ"operator<=>
, যা আপনাকে সংকলক-উত্পাদিত <
/ <=
/ ==
/ !=
/ >=
/ এবং / অথবা >
অপারেটরদের / স্পষ্ট / নিষ্পাপ (?) প্রয়োগের সাথে অনুরোধ করার অনুমতি দেয় ...
auto operator<=>(const MyClass&) const = default;
... তবে আপনি আরও জটিল পরিস্থিতির জন্য এটি কাস্টমাইজ করতে পারেন (নীচে আলোচনা করা হয়েছে)। ভাষা প্রস্তাবের জন্য এখানে দেখুন , এতে ন্যায্যতা এবং আলোচনা রয়েছে। এই উত্তরটি সি ++ 17 এবং তার আগের এবং আপনার কখনই প্রয়োগকরণ কাস্টমাইজ করা উচিত অন্তর্দৃষ্টি জন্য প্রাসঙ্গিক থেকে যায় operator<=>
....
এটি ইতিমধ্যে এটি ইতিমধ্যে মানক না করা কিছুটা অস্বাস্থ্যকর বলে মনে হতে পারে তবে প্রায়শই স্ট্রাইক / ক্লাসগুলির তুলনা থেকে বাদ দেওয়ার জন্য কিছু ডেটা সদস্য থাকে (যেমন কাউন্টার, ক্যাশেড ফলাফল, ধারক ক্ষমতা, শেষ অপারেশন সাফল্য / ত্রুটি কোড, কার্সার) হিসাবে পাশাপাশি অগণিত বিষয়গুলি সম্পর্কে সিদ্ধান্ত নেওয়ার পাশাপাশি সীমাবদ্ধ নয়:
- কোন ক্ষেত্রগুলি প্রথমে তুলনা করতে হবে, উদাহরণস্বরূপ, কোনও নির্দিষ্ট
int
সদস্যের তুলনা করলে খুব দ্রুত 99% অসম বস্তু মুছে ফেলা হতে পারে, তবে map<string,string>
সদস্যের প্রায়শই অভিন্ন প্রবেশাধিকার থাকতে পারে এবং তুলনা করার জন্য তুলনামূলকভাবে ব্যয়বহুল হতে পারে - যদি রানটাইমের সময় মানগুলি লোড হয় তবে প্রোগ্রামারটির অন্তর্দৃষ্টি থাকতে পারে সংকলক সম্ভবত না
- স্ট্রিংগুলির সাথে তুলনা করার ক্ষেত্রে: কেস সংবেদনশীলতা, সাদা স্থান এবং পৃথককারীগুলির সমতুল্যতা, সম্মেলনগুলি পালানোর ...
- স্পেস / ডাবল তুলনা করার সময় নির্ভুলতা
- NaN ভাসমান পয়েন্টের মানগুলি সমান বিবেচনা করা উচিত কিনা
- পয়েন্টার বা পয়েন্ট-টু-ডেটা তুলনা (এবং যদি পরবর্তীটি হয় তবে কীভাবে পয়েন্টারগুলি অ্যারেতে হয় এবং কীভাবে কতগুলি অবজেক্ট / বাইটের তুলনা প্রয়োজন তা জানতে হবে)
- অরসোর্টার্ড কনটেইনার (যেমন
vector
, list
) তুলনা করার সময় অর্ডারটি গুরুত্বপূর্ণ কিনা এবং যদি তাই হয় তবে ভার্সেসের তুলনা করার আগে সেগুলি যথাস্থানে বাছাই করা ঠিক আছে কিনা প্রতিবারের সাথে তুলনা করার পরে অস্থায়ীভাবে বাছাই করার জন্য অতিরিক্ত মেমরি ব্যবহার করে
- বর্তমানে কয়টি অ্যারে উপাদান বৈধ মান ধরেছে যা তুলনা করা উচিত (কোথাও কোনও আকার বা প্রেরণিকা আছে?)
- কোন সদস্যের
union
সাথে তুলনা করা
- নরমালাইজেশন: উদাহরণস্বরূপ, তারিখের প্রকারগুলি মাসের বাইরে বা মাসের মাসের বাইরে-বা সীমানা / ভগ্নাংশের অবজেক্টের 6/8 তম থাকতে পারে এবং অন্যটিতে 3/4 অংশ থাকতে পারে, যা কার্য সম্পাদনের কারণে তারা সংশোধন করে অলসভাবে একটি পৃথক স্বাভাবিককরণের পদক্ষেপ সহ; তুলনার আগে আপনাকে একটি সাধারণীকরণকে ট্রিগার করতে হবে কিনা তা সিদ্ধান্ত নিতে হতে পারে
- দুর্বল পয়েন্টারগুলি বৈধ না হলে কী করবেন
- কীভাবে এমন সদস্য এবং ঘাঁটিগুলি পরিচালনা করবেন যেগুলি তাদের প্রয়োগ
operator==
করে না (তবে তাদের থাকতে পারে compare()
বা operator<
অথবা গ্রাহকরা থাকতে পারে str()
...)
- অন্যান্য থ্রেডগুলি আপডেট করতে পারে এমন ডেটা পড়ার / তুলনা করার সময় অবশ্যই কোন লকগুলি নেওয়া উচিত
সুতরাং, আপনার ত্রুটিযুক্ত কাঠামোর জন্য তুলনাটির অর্থ কী হওয়া উচিত তা স্পষ্টভাবে চিন্তা না করা অবধি ত্রুটি থাকা এক ধরণের সুন্দর কারণ এটি সংকলন করতে দেওয়া কিন্তু রান-টাইমে আপনাকে কোনও অর্থবহ ফলাফল দেয় না ।
যে সমস্ত বলেন, এটা ++ যদি সি আপনি বলা যাক ভালো হতে চাই bool operator==() const = default;
যখন কোন কাজের সিদ্ধান্ত চাই একটি "সরল" সদস্য-বাই-সদস্য ==
পরীক্ষা ছিল ঠিক আছে। একই জন্য !=
। প্রদত্ত একাধিক সদস্য / ঘাঁটি, "ডিফল্ট" <
, <=
, >
, এবং >=
বাস্তবায়নের যদিও আশাহীন বলে মনে হচ্ছে - ঘোষণা এর সম্ভব কিন্তু খুব হতে চেয়েছি, সদস্য ক্রম জন্য শর্তগুলো পরস্পরবিরোধী (ঘাঁটি সদস্যদের সামনে অগত্যা হচ্ছে দ্বারা গোষ্ঠীবদ্ধ দেওয়া অসম্ভাব্য ক্রম ভিত্তিতে ক্যাসকেডিং নির্ভরযোগ্য ব্যবহারের আগে অ্যাক্সেসযোগ্যতা, নির্মাণ / ধ্বংস)। আরও ব্যাপকভাবে দরকারী হতে, সি ++ এর জন্য পছন্দগুলির গাইডেন্স করার জন্য একটি নতুন ডেটা মেম্বার / বেস অ্যানোটেশন সিস্টেমের প্রয়োজন হবে - এটি স্ট্যান্ডার্ডে থাকা দুর্দান্ত জিনিস হবে যদিও আদর্শভাবে এএসটি ভিত্তিক ব্যবহারকারী সংজ্ঞায়িত কোড জেনারেশনের সাথে মিলিত হবে ... আমি আশা করি এটা '
সমতা অপারেটরগুলির সাধারণ বাস্তবায়ন
একটি প্রশংসনীয় বাস্তবায়ন
এটি সম্ভবত যুক্তিসঙ্গত এবং দক্ষ বাস্তবায়ন হতে পারে:
inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return lhs.my_struct2 == rhs.my_struct2 &&
lhs.an_int == rhs.an_int;
}
মনে রাখবেন, এই একটি প্রয়োজন operator==
জন্য MyStruct2
খুব।
নীচে আপনার মাইস্ট্রাক্ট 1 এর সুনির্দিষ্টতার আলোচনার শিরোনামে এই প্রয়োগের প্রভাবগুলি এবং বিকল্পগুলি আলোচনা করা হয়েছে ।
==, <,> <= ইত্যাদির একটি ধারাবাহিক পন্থা
std::tuple
আপনার নিজের শ্রেণীর উদাহরণগুলির সাথে তুলনা করা সহজতর করার তুলনা অপারেটরগুলি - কেবল std::tie
তুলনার পছন্দসই ক্ষেত্রে ক্ষেত্রগুলিতে রেফারেন্সগুলি তৈরি করতে ব্যবহার করুন । এখান থেকে আমার উদাহরণ জেনারেল করা :
inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return std::tie(lhs.my_struct2, lhs.an_int) ==
std::tie(rhs.my_struct2, rhs.an_int);
}
inline bool operator<(const MyStruct1& lhs, const MyStruct1& rhs)
{
return std::tie(lhs.my_struct2, lhs.an_int) <
std::tie(rhs.my_struct2, rhs.an_int);
}
আপনি যখন "নিজস্ব" হন (যেমন সম্পাদনা করতে পারেন, কর্পোরেট এবং তৃতীয় পক্ষের libs সহ একটি উপাদান) আপনি যে শ্রেণীর সাথে তুলনা করতে চান এবং বিশেষত return
বিবৃতি থেকে ফাংশন রিটার্নের ধরণের জন্য সি ++ 14 এর প্রস্তুতি সহ , এটি প্রায়শই ভাল হয় " আপনি যে শ্রেণীর সাথে তুলনা করতে সক্ষম হতে চান তার সাথে সদস্য ফাংশনটি টাই করুন:
auto tie() const { return std::tie(my_struct1, an_int); }
তারপরে উপরের তুলনাগুলি এটিকে সহজতর করুন:
inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return lhs.tie() == rhs.tie();
}
আপনি যদি তুলনা অপারেটরগুলির একটি পূর্ণাঙ্গ সেট চান, তবে আমি আপনাকে অপারেটরদের বুস্ট করার পরামর্শ দেব (অনুসন্ধান করুন less_than_comparable
)। যদি এটি কোনও কারণে অনুপযুক্ত হয়, তবে আপনি সমর্থন ম্যাক্রোগুলি (অনলাইন) এর ধারণাটি পছন্দ করতে বা পছন্দ করতে পারেন :
#define TIED_OP(STRUCT, OP, GET_FIELDS) \
inline bool operator OP(const STRUCT& lhs, const STRUCT& rhs) \
{ \
return std::tie(GET_FIELDS(lhs)) OP std::tie(GET_FIELDS(rhs)); \
}
#define TIED_COMPARISONS(STRUCT, GET_FIELDS) \
TIED_OP(STRUCT, ==, GET_FIELDS) \
TIED_OP(STRUCT, !=, GET_FIELDS) \
TIED_OP(STRUCT, <, GET_FIELDS) \
TIED_OP(STRUCT, <=, GET_FIELDS) \
TIED_OP(STRUCT, >=, GET_FIELDS) \
TIED_OP(STRUCT, >, GET_FIELDS)
... যে পরে একটি লা ব্যবহার করা যেতে পারে ...
#define MY_STRUCT_FIELDS(X) X.my_struct2, X.an_int
TIED_COMPARISONS(MyStruct1, MY_STRUCT_FIELDS)
(সি ++ ১৪ টি সদস্যের টাই সংস্করণ এখানে )
আপনার মাইস্ট্রাক্ট 1 এর নির্দিষ্টকরণের আলোচনা
সদস্যের তুলনায় একটি ফ্রি-স্ট্যান্ডিং সরবরাহের পছন্দটিতে জড়িত রয়েছে operator==()
...
ফ্রিস্ট্যান্ডিং বাস্তবায়ন
আপনি একটি আকর্ষণীয় সিদ্ধান্ত গ্রহণ আছে। যেহেতু আপনার ক্লাসটি স্পষ্টভাবে একটি থেকে তৈরি করা যেতে পারে MyStruct2
, একটি মুক্ত স্থায়ী / সদস্যবিহীন bool operator==(const MyStruct2& lhs, const MyStruct2& rhs)
ফাংশন সমর্থন করবে ...
my_MyStruct2 == my_MyStruct1
... প্রথমে MyStruct1
থেকে একটি অস্থায়ী তৈরি করে my_myStruct2
, তারপর তুলনা করে doing এটি অবশ্যই MyStruct1::an_int
কনস্ট্রাক্টরের ডিফল্ট প্যারামিটার মানকে সেট করবে -1
। কিনা আপনি অন্তর্ভুক্ত উপর নির্ভর করে an_int
আপনার বাস্তবায়নে তুলনা operator==
, একটি MyStruct1
শক্তি বা সমান তুলনা নাও হতে পারে MyStruct2
নিজেই যে এর সমান তুলনা MyStruct1
'র my_struct_2
সদস্য! তদ্ব্যতীত, একটি অস্থায়ী তৈরি MyStruct1
করা একটি খুব অকার্যকর অপারেশন হতে পারে, কারণ এটি বিদ্যমান my_struct2
সদস্যকে অস্থায়ীভাবে অনুলিপি করতে জড়িত , কেবল তুলনার পরে এটিকে ফেলে দিতে। (অবশ্যই, আপনি সেই নির্মাতা তৈরি করে বা MyStruct1
এর জন্য explicit
ডিফল্ট মানটি সরিয়ে তুলনার জন্য এইগুলির অন্তর্নিহিত নির্মাণকে আটকাতে পারেন an_int
))
সদস্য বাস্তবায়ন
আপনি যদি একটি অন্তর্নিহিত নির্মাণ এড়াতে চান তাহলে MyStruct1
A থেকে MyStruct2
তুলনা অপারেটর সদস্য ফাংশন করুন:
struct MyStruct1
{
...
bool operator==(const MyStruct1& rhs) const
{
return tie() == rhs.tie();
}
};
const
কীওয়ার্ডটি নোট করুন - কেবল সদস্য প্রয়োগের জন্য প্রয়োজনীয় - সংকলককে পরামর্শ দেয় যে বস্তুর তুলনা করে সেগুলি সংশোধন করে না, সুতরাং const
বস্তুগুলিতে অনুমতি দেওয়া যেতে পারে ।
দৃশ্যমান উপস্থাপনা তুলনা
কখনও কখনও আপনি যে ধরণের তুলনা চান তা পাওয়ার সহজতম উপায় হতে পারে ...
return lhs.to_string() == rhs.to_string();
... যা প্রায়শই খুব ব্যয়বহুল - যারা string
বেদনাদায়কভাবে তৈরি করা হয়েছিল কেবল তা ফেলে দেওয়ার জন্য! ভাসমান পয়েন্ট মানগুলির সাথে প্রকারের জন্য, দৃশ্যমান উপস্থাপনাগুলির তুলনা করার অর্থ প্রদর্শিত সংখ্যার সংখ্যাটি সহনশীলতা নির্ধারণ করে যার মধ্যে প্রায় সমান মানগুলি তুলনার সময় সমান হিসাবে বিবেচিত হয়।
struct
সমতার জন্য নিজের তুলনা করতে চান ? এবং যদি আপনি সহজ উপায় চান,memcmp
আপনার স্ট্রাইকগুলিতে পয়েন্টার থাকে না এমন সবসময় থাকে।