কেন প্রচুর সি ++ স্ট্যান্ডার্ড লাইব্রেরি কোডে (! (A == b)) হিসাবে বৈষম্য পরীক্ষা করা হয়?


142

এটি সি ++ স্ট্যান্ডার্ড লাইব্রেরি removeকোড থেকে কোড। বৈষম্যের if (!(*first == val))পরিবর্তে কেন পরীক্ষা করা হয় if (*first != val)?

 template <class ForwardIterator, class T>
      ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val)
 {
     ForwardIterator result = first;
     while (first!=last) {
         if (!(*first == val)) {
             *result = *first;
             ++result;
         }
         ++first;
     }
     return result;
 }

2
@ বিয়ারারস্টুডিওগুলি সম্ভবত সঠিক। এটি বাস্তবায়নের সময়ও সাধারণ operator!=। কেবল operator==বাস্তবায়নটি ব্যবহার করুন :bool operator!=(const Foo& other) { return !(*this == other); }
সাইমন

1
আসলে আমি আমার বক্তব্যটি সংশোধন করেছি: রেফারেন্স উল্লেখটি এমন সমস্ত উপাদান সরিয়ে দেয় যা সমান হয় তাই operator==এখানে ব্যবহার করা প্রত্যাশিত ...
BeyelerStudios

ওহ, এবং constআমার আগের মন্তব্যে উদাহরণের মধ্যে একটিও হওয়া উচিত তবে আপনি বিষয়টিটি পেতে পারেন। (এটি সম্পাদনা করতে খুব দেরি হয়েছে)
সাইমন

এর কারণ অন্য একটি প্রশ্নের সাথে (যা মূলত "না, অগত্যা নয়" দিয়ে উত্তর দিতে পারে) এবং EqualityComparableহুর্কিল তার উত্তরে উল্লিখিত সেই ধারণার সাথে সম্পর্কিত ।
মার্কো 13

উত্তর:


144

কারণ এটি টি এর একমাত্র প্রয়োজন হ'ল একটি বাস্তবায়ন করা operator==। আপনার টি থাকতে একটি প্রয়োজন হতে পারে operator!=তবে সাধারণ ধারণাটি হ'ল আপনার টেমপ্লেট ব্যবহারকারীর উপর যতটা সম্ভব চাপ দেওয়া উচিত এবং অন্যান্য টেম্পলেটগুলির প্রয়োজন হয় operator==


13
টেমপ্লেট <ক্লাস টি> ইনলাইন বুল অপারেটর! = <টি টি, টি বি> {রিটার্ন (a == খ); }
জোশুয়া

8
এমন কোনও দৃশ্য আছে যেখানে কোনও সংকলক = এর সমস্ত দৃষ্টান্ত বদলাতে সক্ষম হবে না! থেকে! (==)? কেন এটি ইতিমধ্যে সংকলক গ্রহণের জন্য ডিফল্ট ক্রিয়া হবে না?
আইডান গোমেজ

20
@ আইডনগোমেজ আরও ভাল বা খারাপ আপনি অপারেটরদের যা খুশি করতে ওভারলোড করতে পারেন। এটি বোঝার বা ধারাবাহিক হতে হবে না।
নিল

10
x != yহিসাবে একই হিসাবে সংজ্ঞায়িত করা হয় না !(x == y)। এই অপারেটররা যদি এম্বেডড ডিএসএলের পার্স গাছটি ফেরত দেয় তবে কী হবে?
ব্রাইস এম। ডেম্পসে

7
@ জোশুয়া !=সমর্থিত কিনা তা সনাক্ত করার জন্য SFINAE ব্যবহার করার চেষ্টা করার পরে এটি খারাপভাবে ভেঙে গেছে ( operator==সমর্থিত না হলেও ভুলভাবে সত্যটি প্রত্যাবর্তন করবে !)। আমি এও উদ্বিগ্ন যে এটির কিছু ব্যবহার !=অস্পষ্ট হয়ে উঠবে।

36

এসটিএলে বেশিরভাগ ফাংশন কেবল operator<বা সাথে কাজ করে operator==। এটির জন্য কেবলমাত্র এই দুটি অপারেটর (বা কখনও কখনও তাদের মধ্যে অন্তত একটির) প্রয়োগ করতে হবে। উদাহরণস্বরূপ std::setব্যবহারগুলি operator<(আরও সুনির্দিষ্টভাবে std::lessযা operator<ডিফল্ট অনুসারে আহ্বান জানায় ) এবং operator>ক্রম পরিচালনা করতে না পারে। removeআপনার উদাহরণে টেমপ্লেট একটি অনুরূপ ক্ষেত্রে দেখা যায় - এটি শুধুমাত্র ব্যবহার operator==এবং operator!=তাই operator!=সংজ্ঞায়িত করা প্রয়োজন হবে না।


2
ফাংশনগুলি operator<সরাসরি ব্যবহার না করে পরিবর্তে ব্যবহার করে std::less, যা পরিবর্তে ডিফল্ট হয় operator<
খ্রিস্টান হ্যাকেল

1
প্রকৃতপক্ষে, এটি দেখে মনে হয় যে আদর্শ স্ট্যান্ডার্ড অ্যালগরিদম ফাংশনগুলি যেমন std::set, প্রকৃত পক্ষে operator<সরাসরি ব্যবহার করে না। আজব ...
খ্রিস্টান হ্যাকেল

1
এই ফাংশনগুলি ব্যবহার করে না std::equal_to, তারা operator==প্রশ্নে উল্লিখিত হিসাবে ব্যবহার করে । পরিস্থিতিও std::lessএকই রকম। ভাল, সম্ভবত std::setসেরা উদাহরণ না।
লুকা বেদনায়েক

2
@ খ্রিস্টিয়ানহ্যাকল std::equal_toএবং std::lessডিফল্ট টেম্পলেট প্যারামিটার হিসাবে ব্যবহৃত হয় যেখানে তুলনাকারীকে প্যারামিটার হিসাবে নেওয়া হয়। operator==এবং operator<সরাসরি ব্যবহৃত হয় যেখানে যথাক্রমে সমতা তুলনীয় এবং কঠোর দুর্বল ক্রম যেমন: পুনরাবৃত্তকারী এবং এলোমেলো অ্যাক্সেস পুনরাবৃত্তিকে পূরণ করতে টাইপটির প্রয়োজন হয়।
জান হুডেক

28

এটি সি ++ স্ট্যান্ডার্ড লাইব্রেরি সরানোর কোডের কোড।

ভুল। এটা না C ++ স্ট্যান্ডার্ডের গ্রন্থাগার কোড। এটি সি ++ স্ট্যান্ডার্ড লাইব্রেরি ফাংশনের একটি সম্ভাব্য অভ্যন্তরীণ বাস্তবায়ন । সি ++ স্ট্যান্ডার্ড প্রকৃত কোড নির্ধারণ করে না; এটি ফাংশন প্রোটোটাইপ এবং প্রয়োজনীয় আচরণগুলি নির্ধারণ করে।removeremove

অন্য কথায়: কঠোর ভাষার দৃষ্টিকোণ থেকে, আপনি যে কোডটি দেখছেন তা বিদ্যমান নেই । এটি এমন কোনও শিরোনাম ফাইল হতে পারে যা আপনার সংকলকের মানক-গ্রন্থাগার বাস্তবায়নের সাথে আসে। মনে রাখবেন যে সি ++ স্ট্যান্ডার্ডের এমনকি সেই শিরোনাম ফাইলগুলির অস্তিত্বের প্রয়োজন নেই। ফাইলগুলি কম্পাইলার প্রয়োগকারীদের জন্য লাইনের মতো প্রয়োজনীয়তা মেটাতে #include <algorithm>(যেমন তৈরি std::removeএবং অন্যান্য ফাংশন উপলভ্য) কেবলমাত্র একটি সহজ উপায় ।

বৈষম্যের if (!(*first == val))পরিবর্তে কেন পরীক্ষা করা হয় if (*first != val)?

কারণ শুধুমাত্র operator==ফাংশন দ্বারা প্রয়োজনীয়।

কাস্টম ধরণের জন্য যখন অপারেটর ওভারলোডিংয়ের কথা আসে তখন ভাষা আপনাকে সমস্ত ধরণের অদ্ভুত জিনিস করতে দেয়। আপনি খুব ভালভাবে একটি ক্লাস তৈরি করতে পারেন যা একটি ওভারলোডড operator==কিন্তু কোনও ওভারলোডেড নেই operator!=। বা আরও খারাপ: আপনি ওভারলোড করতে operator!=পারেন তবে এটি সম্পূর্ণ সম্পর্কযুক্ত জিনিস করতে পারে।

এই উদাহরণ বিবেচনা করুন:

#include <algorithm>
#include <vector>

struct Example
{
    int i;

    Example() : i(0) {}

    bool operator==(Example const& other) const
    {
        return i == other.i;
    }

    bool operator!=(Example const& other) const
    {
        return i == 5; // weird, but nothing stops you
                       // from doing so
    }

};

int main()
{
  std::vector<Example> v(10);
  // ...
  auto it = std::remove(v.begin(), v.end(), Example());
  // ...
}

যদি std::removeব্যবহার করা হয় operator!=, তবে ফলাফলটি একেবারেই আলাদা হবে।


1
আরেকটি বিষয় বিবেচনা করে তা হ'ল উভয়ের পক্ষে a==bএবং a!=bমিথ্যা প্রত্যাবর্তন সম্ভব হতে পারে । যদিও এটি সর্বদাই পরিষ্কার নয় যে এই জাতীয় পরিস্থিতিটি আরও অর্থবহভাবে "সমান" বা "সমান নয়" হিসাবে বিবেচিত হবে কিনা, এমন একটি ফাংশন যা কেবলমাত্র "==" অপারেটরের ক্ষেত্রে সাম্যকে সংজ্ঞায়িত করে তাদের অবশ্যই "সম-সমান" হিসাবে বিবেচনা করতে হবে ", কোন আচরণটি আরও অর্থবোধ করবে তা নির্বিশেষে [আমার কাছে যদি আমার ড্রথাররা থাকে তবে সমস্ত ধরণের বুলিয়ান ফলনকারী" == "এবং"! = "অপারেটররা ধারাবাহিকভাবে আচরণ করবে বলে আশা করা হয়েছিল, তবে আইইইই-75৫4 হ'ল আদেশ সমতা ভঙ্গ করেছে অপারেটররা এ জাতীয় প্রত্যাশাকে কঠিন করে তুলবেন]।
সুপারক্যাট

18
"কঠোর ভাষার দৃষ্টিকোণ থেকে, আপনি যে কোডটি দেখছেন তা বিদ্যমান নেই" " - যখন কোনও দৃষ্টিকোণ বলে যে কোনও কিছুর অস্তিত্ব নেই তবে আপনি আসলে সেই জিনিসটির দিকে তাকাচ্ছেন, তখন দৃষ্টিকোণটি ভুল। আসলে মানটি কোডটি বলে না বলে, এটি কেবল এটির উপস্থিতি বলে না :-)
স্টিভ জেসপ

@ স্টিভ জেসোপ: আপনি "কঠোর ভাষা দৃষ্টিকোণ থেকে" ভাষাটি "কঠোরভাবে, ভাষার স্তরে" এর মতো কিছু দিয়ে অভিব্যক্তিটি প্রতিস্থাপন করতে পারেন। মুল বক্তব্যটি হ'ল ওপি পোস্ট করা কোডটি ভাষা মানের উদ্বেগ নয়।
খ্রিস্টান হ্যাকেল

2
@ সুপের্যাট: আইইইই--৫৪ তৈরি করে ==এবং !=ধারাবাহিকভাবে আচরণ করে, যদিও আমি সবসময়ই ভেবেছিলাম যে falseঅন্তত একটি অপারেন্ড হলে সমস্ত ছয়টি সম্পর্কের মূল্যায়ন করা উচিত NaN
বেন ভয়েগট

@ বেনভয়েগ: আহ, ঠিক আছে। এটি দুটি অপারেটরকে একই ভাঙা ফ্যাশনে এমনভাবে আচরণ করে তোলে যে তারা একে অপরের সাথে সামঞ্জস্যপূর্ণ, তবে এখনও সমতার সাথে যুক্ত অন্যান্য সাধারণ অক্ষগুলি লঙ্ঘন করতে পরিচালিত করে (উদাহরণস্বরূপ তারা a == aকে সমর্থন করে না এবং অপারেশনগুলি যে গ্যারান্টি দেয় তাও নয়) সমান মান সমান ফলাফল প্রদান করবে)।
সুপারক্যাট

15

কিছু ভাল উত্তর এখানে। আমি শুধু একটি সামান্য নোট যোগ করতে চেয়েছিলেন।

সমস্ত ভাল গ্রন্থাগারের মতো, স্ট্যান্ডার্ড লাইব্রেরি দুটি (খুব কম) দুটি অত্যন্ত গুরুত্বপূর্ণ নীতিটি মাথায় রেখে তৈরি করা হয়েছে:

  1. আপনার গ্রন্থাগারের ব্যবহারকারীদের উপর ন্যূনতম পরিমাণ দায়িত্ব চাপান যা আপনি এড়িয়ে যেতে পারেন। এর একটি অংশ আপনার ইন্টারফেসটি ব্যবহার করার সময় তাদের কমপক্ষে কাজ করতে হবে। (যেমন কিছু অপারেটর হিসাবে আপনি দূরে যেতে পারেন সংজ্ঞায়িত)। এর অন্য অংশটি তাদের বিস্মিত না করা বা ত্রুটি কোডগুলি পরীক্ষা করার জন্য তাদের প্রয়োজনীয়তা না করে (সুতরাং ইন্টারফেসগুলি ধারাবাহিক রাখুন এবং <stdexcept>জিনিসগুলি যখন ভুল হয় তখন ব্যতিক্রমগুলি ছুঁড়ে ফেলুন )।

  2. সমস্ত যৌক্তিক অপ্রয়োজনীয়তা দূর করুন । সমস্ত তুলনা কেবলমাত্র থেকে operator<নির্ধারণ করা যেতে পারে , সুতরাং ব্যবহারকারীরা অন্যদের সংজ্ঞায়িত করার দাবি কেন করবেন? উদাহরণ:

    (a> খ) সমান (খ <ক)

    (a> = b) সমান! (a <b)

    (a == খ) সমান! ((a <বি) || (খ <a))

    ইত্যাদি।

    এই নোটটি উপর অবশ্যই, এক চাইতে পারি কেন unordered_mapপ্রয়োজন operator==(অন্তত ডিফল্ট অনুসারে) বদলে operator<। উত্তরটি হ'ল একটি হ্যাশ টেবিলের মধ্যে কেবল আমাদের তুলনা হ'ল সাম্যের জন্য। সুতরাং এটি আরও যৌক্তিকভাবে সামঞ্জস্যপূর্ণ (যেমন গ্রন্থাগার ব্যবহারকারীকে আরও বোঝায়) তাদের একটি সমতা অপারেটর সংজ্ঞায়িত করা প্রয়োজন। একটি operator<প্রয়োজন বিভ্রান্তিকর হবে কারণ এটি আপনার প্রয়োজন কেন তা তাত্ক্ষণিকভাবে স্পষ্ট নয়।


10
আপনার দ্বিতীয় বিষয় সম্পর্কে: এমন কিছু প্রকার রয়েছে যা যৌক্তিকভাবে সাম্যের জন্য তুলনা করা যেতে পারে এমনকি কোনও যৌক্তিক আদেশ না থাকলেও বা যার জন্য একটি আদেশ প্রতিষ্ঠা করা খুব কৃত্রিম হবে। উদাহরণস্বরূপ, লাল লাল এবং লাল সবুজ নয়, তবে লাল অন্তর্নিহিতভাবে সবুজ থেকে কম?
খ্রিস্টান হ্যাকেল

1
সম্পূর্ণ একমত. কোনও লজিকাল অর্ডার না থাকায় কেউ এই আইটেমগুলিকে অর্ডার করা পাত্রে সংরক্ষণ করবে না । এগুলি আরও উপযুক্তভাবে একটি অযৌক্তিক পাত্রে সংরক্ষণ করা যেতে পারে যার প্রয়োজন operator==(এবং hash)।
রিচার্ড হেজস

3. যথাসম্ভব কমপক্ষে মান অপারেটরগুলি ওভারলোড করুন । এটি তারা বাস্তবায়নের আরেকটি কারণ !(a==b)। অপারেটরদের অপ্রকাশিত ওভারলোডিংয়ের ফলে সহজেই সি ++ প্রোগ্রাম পুরোপুরি গোলযোগের কারণ হতে পারে (প্লাস, প্রোগ্রামারটিকে পাগল করে তুলবে কারণ তার কোডটি ডিবাগ করা একটি মিশন অসম্ভব হয়ে উঠতে পারে, কারণ কোনও নির্দিষ্ট বাগের অপরাধীকে সন্ধান করা একটি অডিয়াসির অনুরূপ)।
সিনট্যাক্সারর

!((a < b) || (b < a))আরেকটি কম বোল অপারেটর ব্যবহার করে, তাই এটি সম্ভবত দ্রুত
ফিলিপ হাগলুন্ড

1
বাস্তবে তারা তা করে না। সমাবেশ ভাষায় সমস্ত তুলনা একটি বিয়োগ হিসাবে প্রয়োগ করা হয়, তার পরে পতাকা নিবন্ধনে ক্যারি এবং শূন্য বিট পরীক্ষা করে অনুসরণ করা হয়। অন্য সব কিছুই কেবল সিনট্যাকটিক চিনি।
রিচার্ড হেজস 21

8

EqualityComparableধারণা শুধুমাত্র প্রয়োজন যে operator==সংজ্ঞায়িত করা।

ফলস্বরূপ, যে কোনও ক্রিয়াকলাপ যে ধরণের সন্তুষ্টির সাথে কাজ করে বলে দাবি করে সে ধরণের বস্তুর অস্তিত্বের উপর নির্ভর EqualityComparable করতে পারে নাoperator!= । (যদি অতিরিক্ত প্রয়োজনীয়তা না থাকে যা অস্তিত্বকে বোঝায় operator!=)


1

সর্বাধিক প্রতিশ্রুতিবদ্ধ পন্থা হ'ল অপারেটর == কোনও নির্দিষ্ট ধরণের জন্য ডেকে আনা যেতে পারে কিনা তা নির্ধারণের একটি পদ্ধতি অনুসন্ধান করা, এবং তারপরে এটি কেবল তখনই সমর্থন করা যায়; অন্যান্য পরিস্থিতিতে, একটি ব্যতিক্রম নিক্ষেপ করা হবে। তবে আজ অবধি কোনও নির্বিচার অপারেটর এক্সপ্রেশন f == g যথাযথভাবে সংজ্ঞায়িত করা হয়েছে কিনা তা সনাক্ত করার কোনও সঠিক উপায় নেই। জানা ভাল সমাধানের মধ্যে নিম্নলিখিত অনাকাঙ্ক্ষিত গুণাবলী রয়েছে:

  • অপারেটর == অ্যাক্সেসযোগ্য নয় এমন বস্তুর জন্য সংকলন-সময় ব্যর্থ হয়েছে (যেমন, এটি ব্যক্তিগত কারণ)।
  • কলিং অপারেটর == অস্পষ্ট হলে সংকলন-সময়ে ব্যর্থ।
  • অপারেটর == ডিক্লেয়ারেশন সঠিক হলে অপারেটর == সংকলন নাও করতে পারে বলে সঠিক বলে মনে হচ্ছে।

বুস্ট এফএকিউ থেকে: উত্স

==বাস্তবায়নের প্রয়োজনীয়তা বোঝা হচ্ছে তা জেনেও , আপনি কখনও !=প্রয়োগের প্রয়োজনের দ্বারা অতিরিক্ত বোঝা তৈরি করতে চান না ।

আমার জন্য ব্যক্তিগতভাবে এটি সলিড (অবজেক্ট-ওরিয়েন্টেড ডিজাইন) এল অংশ সম্পর্কে - লিসকভের প্রতিস্থাপনের নীতি: "একটি প্রোগ্রামের অবজেক্টগুলিকে সেই প্রোগ্রামের যথার্থতা পরিবর্তন না করে তাদের সাব টাইপের উদাহরণ দিয়ে প্রতিস্থাপনযোগ্য হওয়া উচিত।" এক্ষেত্রে এটি অপারেটর ! = যা আমি == এবং বুলিয়ান যুক্তিকে ইন বিপরীত করতে পারি ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.