এনাম প্রকারের জন্য নেমস্পেস - সেরা অনুশীলন


102

প্রায়শই, একসাথে একাধিক গণিত প্রকারের প্রয়োজন হয়। কখনও কখনও, একটির নাম সংঘর্ষ হয়। এর দুটি সমাধান মাথায় আসে: একটি নেমস্পেস ব্যবহার করুন বা 'বৃহত্তর' এনাম উপাদানগুলির নাম ব্যবহার করুন। তবুও, নেমস্পেসের সমাধানটিতে দুটি সম্ভাব্য বাস্তবায়ন রয়েছে: নেস্টেড এনাম সহ একটি ডামি ক্লাস, বা একটি পূর্ণ ব্লোন্ড নেমস্পেস।

আমি তিনটি পদ্ধতিরই পক্ষে ভাল এবং সন্ধান করছি।

উদাহরণ:

// oft seen hand-crafted name clash solution
enum eColors { cRed, cColorBlue, cGreen, cYellow, cColorsEnd };
enum eFeelings { cAngry, cFeelingBlue, cHappy, cFeelingsEnd };
void setPenColor( const eColors c ) {
    switch (c) {
        default: assert(false);
        break; case cRed: //...
        break; case cColorBlue: //...
        //...
    }
 }


// (ab)using a class as a namespace
class Colors { enum e { cRed, cBlue, cGreen, cYellow, cEnd }; };
class Feelings { enum e { cAngry, cBlue, cHappy, cEnd }; };
void setPenColor( const Colors::e c ) {
    switch (c) {
        default: assert(false);
        break; case Colors::cRed: //...
        break; case Colors::cBlue: //...
        //...
    }
 }


 // a real namespace?
 namespace Colors { enum e { cRed, cBlue, cGreen, cYellow, cEnd }; };
 namespace Feelings { enum e { cAngry, cBlue, cHappy, cEnd }; };
 void setPenColor( const Colors::e c ) {
    switch (c) {
        default: assert(false);
        break; case Colors::cRed: //...
        break; case Colors::cBlue: //...
        //...
    }
  }

19
প্রথমত, আমি রঙিন :: লাল, অনুভূতি: রাগ, ইত্যাদি ব্যবহার করব
আবতিশ শেভ ২

ভাল প্রশ্ন, আমি নেমস্পেস পদ্ধতিটি ব্যবহার করেছি ....;)
মিনিস্কোলোপ

18
"গ" উপসর্গ সব কিছুর পাঠ্যতা ব্যাঘাত করে।
ব্যবহারকারী

8
@ ব্যবহারকারী: কেন, হাঙ্গেরিয়ান আলোচনা খোলার জন্য আপনাকে ধন্যবাদ :)
xtofl

5
মনে রাখবেন যে আপনার এনামের নামটি তেমন রাখার দরকার নেই enum e {...}, এনামগুলি বেনামে থাকতে পারে, অর্থাত্ enum {...}যা নেমস্পেসে বা ক্লাসে আবৃত হওয়ার পরে আরও বেশি বোঝা যায়।
kralyk

উত্তর:


73

আসল সি ++ 03 উত্তর:

সুবিধা থেকে একটি namespace(উপর একটি class) আপনি ব্যবহার করতে পারেন usingঘোষণা যখন আপনি চান।

সমস্যা একটি ব্যবহার করে namespaceযে নামব্যবধান কোডে অন্যত্র সম্প্রসারিত করা যেতে পারে। একটি বড় প্রকল্পে, আপনাকে গ্যারান্টি দেওয়া হবে না যে দুটি স্বতন্ত্র এনামো উভয়ই তাদের বলা হয় বলে মনে করে নাeFeelings

সহজ-সরল কোডের জন্য, আমি একটি ব্যবহার করি struct, কারণ আপনি সম্ভবত বিষয়গুলি সর্বজনীন হতে চান।

আপনি যদি এই অনুশীলনগুলির কোনও করছেন তবে আপনার বক্ররেখার চেয়ে এগিয়ে এবং সম্ভবত এটি আরও পরীক্ষা করার দরকার নেই।

আরও নতুন, সি ++ 11 পরামর্শ:

আপনি যদি সি ++ 11 বা তার পরে ব্যবহার করছেন enum classতবে এনামের নামের মধ্যে এনাম মানগুলি স্পষ্টতই স্কোপ করবে।

এর সাথে enum classআপনি পূর্ণসংখ্যার প্রকারের সাথে অন্তর্নিহিত রূপান্তর এবং তুলনা হারাবেন তবে বাস্তবে যা আপনাকে দ্ব্যর্থক বা বগি কোডটি আবিষ্কার করতে সহায়তা করবে।


4
আমি কাঠামো-ধারণার সাথে একমত এবং প্রশংসা জন্য ধন্যবাদ :)
xtofl

3
+1 আমি সি ++ 11 "এনাম ক্লাস" সিনট্যাক্সটি মনে করতে পারি না। এই বৈশিষ্ট্য ব্যতীত, এনামগুলি অসম্পূর্ণ।
গ্রেট

"এনাম ক্লাস" এর অন্তর্নিহিত সুযোগের জন্য "ব্যবহার করে" ব্যবহার করার কি তাদের বিকল্প? উদাহরণস্বরূপ 'রঙ :: ই ব্যবহার করে' যুক্ত করবে; কোডটি 'সিআরড' ব্যবহারের অনুমতি দেয় এবং এটির বর্ণ :: ই :: সিআরড হওয়া উচিত?
JVApen


11

আমি এর আগে এমন কিছুগুলির পূর্ববর্তী উত্তরগুলিকে সংকরিত করেছি: (সম্পাদনা: এটি কেবলমাত্র প্রাক-সি ++ 11 এর জন্য কার্যকর you আপনি যদি সি ++ 11 ব্যবহার করেন তবে ব্যবহার করুন enum class)

আমার কাছে একটি বড় শিরোনামের ফাইল আছে যাতে আমার সমস্ত প্রকল্প এনাম রয়েছে, কারণ এই এনামগুলি শ্রমিক শ্রেণির মধ্যে ভাগ করা হয় এবং শ্রমিকদের ক্লাসগুলিতে এনামগুলিকে নিজেরাই রাখার কোনও মানে হয় না।

structঅন্বিত চিনি, এবং: সর্বজনীন এড়াতে typedefআপনি আসলে অন্যান্য কর্মী শ্রেণীর মধ্যে এই enums এর ভেরিয়েবল ডিক্লেয়ার করতে দেয়।

আমি মনে করি না যে নেমস্পেস ব্যবহার করা মোটেই সহায়তা করে। হয়তো এই কারণ আমি একটি সি # প্রোগ্রামার, এবং আপনি সেখানে আছে যখন মান উল্লেখ enum নাম, ব্যবহার করতে তাই আমি এটা ব্যবহার করছি।

    struct KeySource {
        typedef enum { 
            None, 
            Efuse, 
            Bbram
        } Type;
    };

    struct Checksum {
        typedef enum {
            None =0,
            MD5 = 1,
            SHA1 = 2,
            SHA2 = 3
        } Type;
    };

    struct Encryption {
        typedef enum {
            Undetermined,
            None,
            AES
        } Type;
    };

    struct File {
        typedef enum {
            Unknown = 0,
            MCS,
            MEM,
            BIN,
            HEX
        } Type;
    };

...

class Worker {
    File::Type fileType;
    void DoIt() {
       switch(fileType) {
       case File::MCS: ... ;
       case File::MEM: ... ;
       case File::HEX: ... ;
    }
}

9

আমি অবশ্যই এই জন্য একটি ক্লাস ব্যবহার এড়াতে হবে; পরিবর্তে একটি নেমস্পেস ব্যবহার করুন। নাম স্থানটি ব্যবহার করতে হবে বা এনাম মানগুলির জন্য অনন্য আইডি ব্যবহার করতে হবে কিনা তা নিয়ে প্রশ্নটি উত্থিত হয়। ব্যক্তিগতভাবে, আমি একটি নেমস্পেস ব্যবহার করব যাতে আমার আইডিগুলি সংক্ষিপ্ততর হয় এবং আশা করা যায় যে আরও স্ব-ব্যাখ্যাযোগ্য। তারপরে অ্যাপ্লিকেশন কোডটি 'নেমস্পেস ব্যবহার করে' নির্দেশিকা ব্যবহার করতে পারে এবং সবকিছুকে আরও পাঠযোগ্য।

আপনার উপরের উদাহরণ থেকে:

using namespace Colors;

void setPenColor( const e c ) {
    switch (c) {
        default: assert(false);
        break; case cRed: //...
        break; case cBlue: //...
        //...
    }
}

আপনি কেন কোনও শ্রেণীর চেয়ে নেমস্পেস পছন্দ করবেন সে বিষয়ে ইঙ্গিত দিতে পারেন ?
xtofl

@xtofl: আপনি 'ক্লাস কালার্স ব্যবহার করে লিখতে পারবেন না
এমএসএলটাররা

2
@ এসএমএলটার্স: আপনি লিখতেও পারবেন না Colors someColor = Red;, কারণ নেমস্পেস কোনও ধরণের গঠন করে না। Colors::e someColor = Red;পরিবর্তে আপনাকে লিখতে হবে, যা বেশ স্ব-স্বজ্ঞাত।
সাসকিউ

@SasQ ব্যাপারে ব্যবহার করতে হবে না Colors::e someColorএকটি এমনকি struct/classযদি আপনি একটি এটি ব্যবহার করতে চেয়েছিলেন switchবক্তব্য? আপনি যদি কোনও বেনাম ব্যবহার করেন enumতবে স্যুইচটি একটিটির মূল্যায়ন করতে সক্ষম হবে না struct
ম্যাকবেথের এনিগমা

1
দুঃখিত, তবে const e cআমার কাছে খুব পঠনযোগ্য বলে মনে হচ্ছে :-) এটি করবেন না। নেমস্পেস ব্যবহার করা ঠিক আছে।
ধৈমন

7

ক্লাস বা নেমস্পেস ব্যবহারের মধ্যে পার্থক্য হ'ল ক্লাসটি নামের জায়গার মতো আবার খোলা যায় না। এটি ভবিষ্যতে নামের স্থানটি অপব্যবহারের সম্ভাবনা এড়িয়ে চলে, তবে এমন একটি সমস্যাও রয়েছে যা আপনি গণনার সংকলনে যোগ করতে পারবেন না।

কোনও শ্রেণি ব্যবহারের জন্য একটি সম্ভাব্য সুবিধা হ'ল এগুলি টেমপ্লেট ধরণের আর্গুমেন্ট হিসাবে ব্যবহার করা যেতে পারে, যা নেমস্পেসগুলির ক্ষেত্রে নয়:

class Colors {
public:
  enum TYPE {
    Red,
    Green,
    Blue
  };
};

template <typename T> void foo (T t) {
  typedef typename T::TYPE EnumType;
  // ...
}

ব্যক্তিগতভাবে, আমি ব্যবহারের অনুরাগী নই , এবং আমি সম্পূর্ণরূপে যোগ্যতাসম্পন্ন নাম পছন্দ করি, তাই নামের জায়গাগুলির জন্য প্লাস হিসাবে আমি সত্যিই দেখতে পাই না। তবে, এটি সম্ভবত আপনার প্রকল্পে নেওয়া সবচেয়ে গুরুত্বপূর্ণ সিদ্ধান্ত নয়!


ক্লাস পুনরায় চালু না করাও একটি সম্ভাব্য অসুবিধা। রঙগুলির তালিকাও সীমাবদ্ধ নয়।
এমসাল্টাররা

1
আমি মনে করি কোনও ক্লাস পুনরায় করা না করা একটি সম্ভাব্য সুবিধা। আমি যদি আরও রঙ চাই, আমি কেবল আরও রঙ সহ ক্লাসটি পুনরায় সংকলন করব। যদি আমি এটি করতে না পারি (বলুন আমার কাছে কোড নেই) তবে আমি কোনও অবস্থাতেই এটি স্পর্শ করতে চাই না।
টমাস এডিং

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

সুতরাং আপনি যখন এনামটি প্রসারিত করতে চান, আপনার এটিকে প্রথম থেকে উদ্ভূত একটি নতুন ধরণের করা উচিত (কেবলমাত্র যদি এটি সি ++ ... ... / / এ সহজেই সম্ভব হত)। তারপরে এটি নিরাপদে নতুন কোড দ্বারা ব্যবহার করা যেতে পারে যা সেই নতুন মানগুলি বোঝে, তবে কেবলমাত্র পুরাতন মানগুলি পুরানো কোড দ্বারা স্বীকৃত হবে (সেগুলি রূপান্তর করে)। ভুল ধরণের (বর্ধিত) হওয়ায় নতুন মানগুলি থেকে তাদের কোনও গ্রহণ করা উচিত নয়। তারা যে পুরানো মানগুলি বুঝতে পেরেছে কেবল সেগুলি সঠিক (বেস) প্রকারের হিসাবে গ্রহণযোগ্য (এবং দুর্ঘটনাক্রমে নতুন ধরণেরও রয়েছে, তাই এটি নতুন কোড দ্বারাও গৃহীত হতে পারে)।
সাসকিউ

7

কোনও শ্রেণি ব্যবহারের সুবিধা হ'ল এটির উপরে আপনি একটি পূর্ণাঙ্গ শ্রেণি তৈরি করতে পারেন।

#include <cassert>

class Color
{
public:
    typedef enum
    {
        Red,
        Blue,
        Green,
        Yellow
    } enum_type;

private:
    enum_type _val;

public:
    Color(enum_type val = Blue)
        : _val(val)
    {
        assert(val <= Yellow);
    }

    operator enum_type() const
    {
        return _val;
    }
};

void SetPenColor(const Color c)
{
    switch (c)
    {
        case Color::Red:
            // ...
            break;
    }
}

উপরের উদাহরণটি যেমন দেখায়, ক্লাস ব্যবহার করে আপনি এটি করতে পারেন:

  1. নিষিদ্ধ করুন (দুঃখের সাথে, সংকলন-সময় নয়) সি ++ অবৈধ মান থেকে castালাইকে অনুমতি দেওয়া থেকে,
  2. সদ্য নির্মিত এনামগুলির জন্য একটি (শূন্য নয়) ডিফল্ট সেট করুন,
  3. আরও পদ্ধতি যুক্ত করুন, যেমন কোনও পছন্দের স্ট্রিং প্রতিনিধিত্ব ফিরিয়ে দেওয়ার মতো।

কেবলমাত্র নোট করুন যে আপনাকে ঘোষণা করতে হবে operator enum_type()যাতে সি ++ আপনার ক্লাসকে অন্তর্নিহিত এনামে রূপান্তর করতে পারে তা জানতে পারে। অন্যথায়, আপনি কোনও switchবিবৃতিতে টাইপটি পাস করতে পারবেন না ।


এই সমাধানটি এখানে কীভাবে দেখানো হয়েছে তার সাথে কি কোনওভাবে সম্পর্কিত ?: en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Type_Safe_Enum আমি কীভাবে এটি একটি টেমপ্লেট তৈরি করব তা নিয়ে ভাবছি যা আমাকে প্রতিবার এই প্যাটার্নটি আবার লিখতে হবে না I'm আমার এটি ব্যবহার করা দরকার
সাসকিউ

@ সাসকিউ: হ্যাঁ, এটি একই রকম মনে হচ্ছে। সম্ভবত এটি একই ধারণা। তবে, আমি নিশ্চিত না যে আপনি যদি সেখানে প্রচুর 'প্রচলিত' পদ্ধতি যুক্ত না করেন তবে কোনও টেম্পলেটটি উপকারী কিনা।
মিশা গার্নি

1. সত্য নয়। আপনার কমপাইল সময় পরীক্ষা করতে পারেন যে এনামটি বৈধ, কনস্ট_এক্সপ্রেসের মাধ্যমে, বা কোনও প্রাইভেট কনস্ট্রাক্টরের মাধ্যমে একটি ইন্টের জন্য।
xryl669

5

যেহেতু এনামগুলি তাদের ঘেরের স্কোপে বিস্তৃত হয় তাই বিশ্বব্যাপী নেমস্পেসকে দূষিত করা এড়াতে এবং নামের সংঘর্ষ এড়াতে সহায়তা করার জন্য এগুলি কোনও কিছুতে জড়িয়ে রাখা ভাল। আমি ক্লাসের কাছে একটি নেমস্পেসকে পছন্দ করি কারণ namespaceএটি হোল্ডিং ব্যাগের classমতো মনে হয় , অন্যদিকে শক্তিশালী বস্তুর মতো মনে হয় (সিএফ। structবনাম classবিতর্ক)। একটি নেমস্পেসের একটি সম্ভাব্য সুবিধা হ'ল এটি পরে বাড়ানো যেতে পারে - আপনি যদি তৃতীয় পক্ষের কোডটি ব্যবহার করেন যা আপনি সংশোধন করতে পারবেন না এমন ক্ষেত্রে দরকারী।

যখন আমরা সি ++ 0x এর সাথে এনাম ক্লাস পাই তখন এটি অবশ্যই কার্যকর হয়।


এনাম ক্লাস ... তা সন্ধান করা দরকার!
xtofl

3

আমি আমার enums ক্লাসে মোড়ানো ঝোঁক।

রিচার্ড কর্ডেন দ্বারা চিহ্নিত হিসাবে, একটি শ্রেণীর সুবিধা হ'ল এটি সি ++ অর্থে একটি প্রকার এবং তাই আপনি এটি টেমপ্লেটগুলি সহ ব্যবহার করতে পারেন।

আমার বিশেষ টুলবক্স :: আমার প্রয়োজনীয়তার জন্য এনাম ক্লাস যা আমি প্রতিটি টেম্পলেটগুলির জন্য বিশেষায়িত করি যা বুনিয়াদি ফাংশন সরবরাহ করে (মূলত: একটি স্ট্যান্ড :: স্ট্রিংয়ের জন্য এনুম মানকে ম্যাপিং করে যাতে I / O পড়া সহজ হয়)।

আমার সামান্য টেম্পলেটটিতে অনুমোদিত মানগুলি সত্যই যাচাইয়ের অতিরিক্ত সুবিধা রয়েছে। সংকলকটি মানটি সত্যই এনামে রয়েছে কিনা তা যাচাই করার ক্ষেত্রে এক ধরণের শিথিল:

typedef enum { False: 0, True: 2 } boolean;
   // The classic enum you don't want to see around your code ;)

int main(int argc, char* argv[])
{
  boolean x = static_cast<boolean>(1);
  return (x == False || x == True) ? 0 : 1;
} // main

এটি সর্বদা আমাকে বিরক্ত করে যে সংকলকটি এটি ধরবে না, যেহেতু আপনি এমন একটি এনাম মান রেখে গেছেন যার কোনও বুদ্ধি নেই (এবং এটি আপনি আশা করবেন না)।

একইভাবে:

typedef enum { Zero: 0, One: 1, Two: 2 } example;

int main(int argc, char* argv[])
{
  example y = static_cast<example>(3);
  return (y == Zero || y == One || y == Two) ? 0 : 1;
} // main

আবার প্রধান একটি ত্রুটি ফিরে আসবে।

সমস্যাটি হ'ল সংকলক উপলব্ধ ক্ষুদ্রতম উপস্থাপনায় এনামকে ফিট করবে (এখানে আমাদের 2 বিট লাগবে) এবং এই উপস্থাপনে যা কিছু ফিট হয় তা একটি বৈধ মান হিসাবে বিবেচিত হয়।

এমন সমস্যাটিও রয়েছে যে কখনও কখনও আপনি পরিবর্তনের পরিবর্তে সম্ভাব্য মানগুলিতে একটি লুপ রাখতে চান যাতে প্রতিবার এনামের সাথে একটি মান যুক্ত করার সময় আপনাকে সমস্ত সুইচ পরিবর্তন করতে হবে না।

আমার সমস্ত সামান্য সহায়ক আমার এনামদের জন্য সত্যই জিনিসগুলি সহজ করে দেয় (অবশ্যই এটি কিছুটা ওভারহেড যুক্ত করে) এবং এটি কেবলমাত্র সম্ভব কারণ আমি প্রত্যেকটি এনামকে তার নিজস্ব কাঠামোতে বাসা করি :)


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