কীভাবে স্ট্যান্ড :: বিকল্প ব্যবহার করা উচিত?


133

আমি এর ডকুমেন্টেশন পড়ছি std::experimental::optionalএবং এটি কী করে সে সম্পর্কে আমার ভাল ধারণা রয়েছে তবে কখন এটি ব্যবহার করা উচিত বা আমার কীভাবে এটি ব্যবহার করা উচিত তা আমি বুঝতে পারি না । সাইটটিতে এখনও পর্যন্ত এমন কোনও উদাহরণ নেই যা আমার পক্ষে এই বিষয়টির আসল ধারণাটি ধরে রাখা আরও কঠিন করে। কখন std::optionalব্যবহার করা ভাল পছন্দ, এবং এটি পূর্ববর্তী স্ট্যান্ডার্ড (সি ++ 11) তে পাওয়া যায় নি তার জন্য কীভাবে ক্ষতিপূরণ দেয়।


19
Boost.optional ডক্স কিছু হালকা চালা পারে।
juanchopanza

স্ট্যান্ড :: ইউনিক_পিটারের মতো মনে হয় সাধারণভাবে একই ব্যবহারের ক্ষেত্রে পরিবেশন করতে পারে। আমার ধারণা যদি আপনার কাছে নতুনের বিরুদ্ধে কোনও জিনিস থাকে তবে alচ্ছিকটি পছন্দনীয় হতে পারে তবে আমার কাছে মনে হয় (নতুন বিকাশকারী | অ্যাপস) নতুন সম্পর্কে এই জাতীয় মতামত সহ একটি সংখ্যালঘু সংখ্যায় রয়েছে ... আফ্রিকান, alচ্ছিক কোনও দুর্দান্ত ধারণা নয়। খুব কমপক্ষে, আমাদের বেশিরভাগ এটি ছাড়া আরাম করে বাঁচতে পারত। ব্যক্তিগতভাবে, আমি এমন এক পৃথিবীতে আরও স্বাচ্ছন্দ্য বোধ করি যেখানে আমাকে অনন্য_পাত্র বনাম alচ্ছিকর মধ্যে বেছে নিতে হবে না। আমাকে পাগল বলুন, তবে পাইথনের জেন ঠিক বলেছেন: কিছু করার একটা সঠিক উপায় হোক!
অ্যালিওরকোড

19
আমরা সবসময় যে গাদা মুছে ফেলতে হয় তার জন্য কিছু বরাদ্দ করতে চাই না, তাই কোনও অনন্য_পিটার চ্ছিক বিকল্প নয়।
ক্রুম

5
@allyourcode কোনও পয়েন্টার এর বিকল্প নয় optional। আপনি একটি optional<int>বা এমনকি চান কল্পনা করুন <char>। আপনি কি সত্যিই মনে করেন যে এটি "জেন" গতিশীলরূপে বরাদ্দ, ডিসেরফেরেন্স, এবং তারপরে মুছতে হবে - এমন কোনও কিছু যা অন্যথায় কোনও বরাদ্দ প্রয়োজন হয় না এবং স্ট্যাকের উপর কমপ্যাক্টভাবে ফিট করতে পারে, এবং এমনকি কোনও রেজিস্টারেও?
আন্ডারস্কোর_

1
আর একটি পার্থক্য, যার ফলে থাকা সঞ্চিত মানের স্ট্যাক বনাম হিপ বরাদ্দ থেকে সন্দেহ নেই, এটি হ'ল টেমপ্লেট যুক্তিটি std::optional(যদিও এটি হতে পারে std::unique_ptr) ক্ষেত্রে অসম্পূর্ণ প্রকার হতে পারে না । আরও স্পষ্টভাবে, স্ট্যান্ডার্ডটির প্রয়োজন যে টি [...] ধ্বংসাত্মকগুলির প্রয়োজনীয়তা পূরণ করবে
ড্যান_দিন_প্যান্টেলিমন

উত্তর:


172

সবচেয়ে সহজ উদাহরণ যা আমি ভাবতে পারি:

std::optional<int> try_parse_int(std::string s)
{
    //try to parse an int from the given string,
    //and return "nothing" if you fail
}

পরিবর্তে (নিম্নলিখিত স্বাক্ষর হিসাবে) একটি রেফারেন্স যুক্তি দিয়ে একই জিনিস সম্পাদন করা যেতে পারে তবে std::optionalব্যবহারটি স্বাক্ষর এবং ব্যবহারকে আরও সুন্দর করে তোলে।

bool try_parse_int(std::string s, int& i);

এটি করার আরেকটি উপায় বিশেষত খারাপ :

int* try_parse_int(std::string s); //return nullptr if fail

এর জন্য গতিশীল মেমরি বরাদ্দ প্রয়োজন, মালিকানা সম্পর্কে চিন্তা করা ইত্যাদি - উপরের অন্যান্য দুটি স্বাক্ষরের মধ্যে সর্বদা পছন্দ করুন।


আরেকটি উদাহরণ:

class Contact
{
    std::optional<std::string> home_phone;
    std::optional<std::string> work_phone;
    std::optional<std::string> mobile_phone;
};

এটি std::unique_ptr<std::string>প্রতিটি ফোন নম্বরগুলির মতো কিছু রাখার চেয়ে চূড়ান্ত ! std::optionalআপনাকে ডেটা লোকাল দেয় যা পারফরম্যান্সের জন্য দুর্দান্ত।


আরেকটি উদাহরণ:

template<typename Key, typename Value>
class Lookup
{
    std::optional<Value> get(Key key);
};

যদি অনুসন্ধানের কোনও নির্দিষ্ট কী না থাকে তবে আমরা কেবল "কোনও মূল্য নেই" ফিরতে পারি।

আমি এটি এর মতো ব্যবহার করতে পারি:

Lookup<std::string, std::string> location_lookup;
std::string location = location_lookup.get("waldo").value_or("unknown");

আরেকটি উদাহরণ:

std::vector<std::pair<std::string, double>> search(
    std::string query,
    std::optional<int> max_count,
    std::optional<double> min_match_score);

এটি বলার চেয়ে অনেক বেশি অর্থবোধ করে যে বলে, চারটি ফাংশন ওভারলোড যা প্রতিটি সম্ভাব্য সংমিশ্রণ গ্রহণ করে max_count(বা না) এবং min_match_score(বা না)!

এছাড়া ঘটিয়েছে অভিশপ্ত "পাস -1জন্য max_countআপনি একটি সীমা চাই না" বা "পাস std::numeric_limits<double>::min()জন্য min_match_scoreআপনি একটি সর্বনিম্ন স্কোর চাই না"!


আরেকটি উদাহরণ:

std::optional<int> find_in_string(std::string s, std::string query);

যদি ক্যোয়ারী স্ট্রিংটি না থাকে তবে sআমি "না int" চাই - কেউ এই উদ্দেশ্যে (-1?) ব্যবহার করার সিদ্ধান্ত নেয় এমন কোনও বিশেষ মান নয়


অতিরিক্ত উদাহরণগুলির জন্য, আপনি boost::optional ডকুমেন্টেশনটি দেখতে পারেনboost::optionalএবংstd::optional আচরণ এবং ব্যবহারের ক্ষেত্রে মূলত অভিন্ন হবে।


13
@gnzlbg std::optional<T>কেবলমাত্র Tএবং একটি bool। সদস্য ফাংশন বাস্তবায়ন অত্যন্ত সহজ। এটি ব্যবহার করার সময় পারফরম্যান্সটি সত্যই উদ্বেগের বিষয় হওয়া উচিত নয় - এমন সময় রয়েছে যখন কিছু alচ্ছিক হয়, সেই ক্ষেত্রে এটি প্রায়শই কাজের জন্য সঠিক সরঞ্জাম।
তীমথিয় শিল্ডস

8
@ টিমোথিশিল্ডস এর std::optional<T>চেয়ে অনেক জটিল। এটি newযথাযথ প্রান্তিককরণ এবং আকার সহ প্লেসমেন্ট এবং আরও অনেক কিছু ব্যবহার করে যাতে এটি constexprঅন্যান্য জিনিসগুলির মধ্যে আক্ষরিক ধরণের (অর্থাত্‍ ব্যবহার করে ) তৈরি করতে পারে। নিষ্পাপ Tএবং boolপদ্ধতির বেশ দ্রুত ব্যর্থ হবে।
Rapptz

15
@Rapptz লাইন 256: union storage_t { unsigned char dummy_; T value_; ... }লাইন 289: struct optional_base { bool init_; storage_t<T> storage_; ... }কিভাবে যে না "একটি Tএবং একটি bool"? আমি সম্পূর্ণরূপে সম্মতি দিচ্ছি যে বাস্তবায়নটি খুব কৌতূহলপূর্ণ এবং অযৌক্তিক, তবে ধারণা এবং দৃ and়ভাবে প্রকারটি একটি Tএবং একটি bool। "নিষ্পাপ Tএবং boolপদ্ধতির খুব দ্রুত ব্যর্থ হবে।" কোডটি দেখার সময় আপনি এই বিবৃতিটি কীভাবে তৈরি করতে পারেন?
তীমথিয় শিল্ডস

12
@ র্যাপ্টজ এটি এখনও একটি বাল এবং একটি অন্তর্নির্মিত স্থান সঞ্চয় করে রাখছে। ইউনিয়নটি কেবল সেখানে অপশনাল টি টি নির্মাণ না করার জন্য রয়েছে যদি এটি আসলে না চায়। এটি struct{bool,maybe_t<T>}ইউনিয়ন এখনও আছে না struct{bool,T}যা করতে সব ক্ষেত্রে একটি টি নির্মাণ করতে পারে।
পিটারটি

12
@allyourcode খুব ভাল প্রশ্ন। উভয়ই std::unique_ptr<T>এবং std::optional<T>কিছুটা অর্থে "একটি alচ্ছিক" ভূমিকাটি সম্পাদন করে T। আমি হিসাবে "বাস্তবায়ন বিবরণ" তাদের মধ্যে পার্থক্য বর্ণনা করবেন: অতিরিক্ত বরাদ্দ, মেমরি ব্যবস্থাপনা, ডেটা স্থান, পদক্ষেপ খরচ, ইত্যাদি আমি না হবে std::unique_ptr<int> try_parse_int(std::string s);উদাহরণস্বরূপ, কারণ এটি প্রতি কলের জন্য একটি বরাদ্দ সেখানে কোনো কারণ যদিও কারণ হবে । আমি কখনই ক্লাস std::unique_ptr<double> limit;করব না - কেন বরাদ্দ রাখি এবং ডেটা লোকাল হারাব?
টিমোথি শিল্ডস

35

নতুন গৃহীত কাগজ থেকে একটি উদাহরণ উদ্ধৃত হয়েছে : N3672, স্টাড :: alচ্ছিক :

 optional<int> str2int(string);    // converts int to string if possible

int get_int_from_user()
{
     string s;

     for (;;) {
         cin >> s;
         optional<int> o = str2int(s); // 'o' may or may not contain an int
         if (o) {                      // does optional contain a value?
            return *o;                  // use the value
         }
     }
}

13
কারণ আপনি একটি "ত্রুটি" অর্থের জন্য কিছু "ভুত" মান "ধরে নেওয়া" এর পরিবর্তে পাস করার পরিবর্তে কল হায়ারার্কি পেয়েছেন বা না পেয়েছেন কিনা সে বিষয়ে আপনি তথ্যটি পাস করতে পারেন int
লুইস মাচুকা

1
@ উইজ এটি আসলে একটি দুর্দান্ত উদাহরণ। এটি (এ) str2int()রূপান্তরটি যেমনটি চায় তা বাস্তবায়িত করতে দেয় , (খ) প্রাপ্তির পদ্ধতি নির্বিশেষে string sএবং (সি) optional<int>কিছু বোকা যাদু-সংখ্যা, bool/ রেফারেন্স বা গতিশীল-বরাদ্দ ভিত্তিক উপায়ের পরিবর্তে সম্পূর্ণ অর্থ জানায় এটা করছি.
আন্ডারস্কোর_

10

তবে কখনই এটি ব্যবহার করা উচিত বা আমার এটি কীভাবে ব্যবহার করা উচিত তা আমি বুঝতে পারি না।

আপনি যখন কোনও এপিআই লিখছেন এবং বিবেচনা করুন যে আপনি "রিটার্ন না থাকা" মানটি ত্রুটি নয় তা প্রকাশ করতে চান। উদাহরণস্বরূপ, আপনাকে একটি সকেট থেকে ডেটা পড়তে হবে এবং যখন কোনও ডেটা ব্লক সম্পূর্ণ হয়ে যায়, আপনি এটি বিশ্লেষণ করে ফিরে আসুন:

class YourBlock { /* block header, format, whatever else */ };

std::optional<YourBlock> cache_and_get_block(
    some_socket_object& socket);

যদি সংযুক্ত ডেটা পার্সেবল ব্লকটি সম্পন্ন করে, আপনি এটি প্রক্রিয়া করতে পারেন; অন্যথায়, ডেটা পড়তে এবং সংযোজন করতে থাকুন:

void your_client_code(some_socket_object& socket)
{
    char raw_data[1024]; // max 1024 bytes of raw data (for example)
    while(socket.read(raw_data, 1024))
    {
        if(auto block = cache_and_get_block(raw_data))
        {
            // process *block here
            // then return or break
        }
        // else [ no error; just keep reading and appending ]
    }
}

সম্পাদনা করুন: আপনার বাকি প্রশ্নগুলি সম্পর্কে:

স্ট্যান্ড :: যখন ::চ্ছিক ব্যবহার করার জন্য একটি ভাল পছন্দ

  • যখন আপনি কোনও মান গণনা করেন এবং এটি ফেরত দেওয়ার দরকার হয়, তখন আউটপুট মানের (যা উত্পন্ন করা যায় না) উল্লেখ করার চেয়ে মানক দিয়ে আরও ভাল শব্দার্থকে ফেরত দেয়।

  • আপনি যে ক্লায়েন্ট কোড নিশ্চিত করার চান, তখন হয়েছে আউটপুট মান (যে কেহ ক্লায়েন্ট কোড লিখেছেন ত্রুটির জন্য পরীক্ষা নাও হতে পারে চেক করতে - আপনি একটি অ-সক্রিয়া পয়েন্টার আপনি একটি কোর ডাম্প পেতে ব্যবহার করার প্রচেষ্টা যদি আপনি একটি নি: - ব্যবহার করার প্রচেষ্টা প্রারম্ভিক স্টাড :: alচ্ছিক, আপনি একটি ধরা-সক্ষম ব্যতিক্রম পাবেন)।

[...] এবং এটি পূর্ববর্তী স্ট্যান্ডার্ড (সি ++ 11) যা পাওয়া যায় নি তার জন্য কীভাবে ক্ষতিপূরণ দেয়?

সি ++ ১১ এর পূর্বে আপনাকে "ফাংশনগুলির জন্য কোনও মান ফেরত দিতে পারে না" এর জন্য আপনাকে একটি আলাদা ইন্টারফেস ব্যবহার করতে হয়েছিল - হয় পয়েন্টার দিয়ে ফিরে আসুন এবং এনএইউএল জন্য চেক করুন, অথবা একটি আউটপুট প্যারামিটার গ্রহণ করুন এবং "উপলভ্য নয়" এর জন্য একটি ত্রুটি / ফলাফল কোড ফিরিয়ে আনুন "।

উভয়ই ক্লায়েন্ট প্রয়োগকারীর কাছ থেকে এটি সঠিকভাবে পেতে অতিরিক্ত প্রচেষ্টা এবং মনোযোগ আরোপ করে এবং উভয়ই বিভ্রান্তির উত্স হয় (প্রথমটি ক্লায়েন্ট প্রয়োগকারীকে বরাদ্দ হিসাবে কোনও ক্রিয়াকলাপ হিসাবে ভাবতে বাধ্য করে এবং ক্লায়েন্ট কোডটি পয়েন্টার-হ্যান্ডলিং যুক্তি বাস্তবায়নের জন্য প্রয়োজনীয় হয় এবং দ্বিতীয়টি অনুমতি দেয় অবৈধ / অনির্দিষ্ট মান ব্যবহার করে ক্লায়েন্ট কোড থেকে দূরে যেতে)।

std::optional পূর্ববর্তী সমাধানগুলির সাথে উত্পন্ন সমস্যার যত্ন সহকারে নেয়।


আমি জানি তারা মূলত একই, তবে কেন আপনি এর boost::পরিবর্তে ব্যবহার করছেন std::?
0x499602D2

4
ধন্যবাদ - আমি এটিকে সংশোধন করেছি (এটি ব্যবহার boost::optionalকরার প্রায় দুই বছর পরে আমি এটি ব্যবহার করেছি, এটি আমার পূর্ব-সম্মুখবর্তী কর্টেক্সে কঠোরভাবে কোডেড)।
utnapistim

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

তুমি ঠিক বলছো; এটি একটি দুর্বল উদাহরণ ছিল; "উপলব্ধ থাকলে প্রথম ব্লককে পার্স করুন" এর জন্য আমি আমার উদাহরণটি পরিবর্তন করেছি।
utnapistim

4

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

এটি "সেট না করা" এর মান "খালি" সমতুল্য নয় তা প্রদর্শন করতে পারে। ধারণা অনুসারে, কোন int (int * p) এর পয়েন্টার এটি প্রদর্শন করতে পারে, যেখানে নাল (p == 0) সেট করা নেই, 0 (* p == 0) এর মান সেট এবং খালি এবং অন্য কোনও মান রয়েছে (* p <> 0) একটি মান সেট করা আছে।

ব্যবহারিক উদাহরণের জন্য, আমার কাছে এক্সএমএল ডকুমেন্ট থেকে জ্যামিতির টুকরো রয়েছে যা রেন্ডার ফ্ল্যাগ নামে একটি মান ছিল, যেখানে জ্যামিতি হয় রেন্ডার ফ্ল্যাগগুলি (সেট) ওভাররাইড করতে পারে, রেন্ডার ফ্ল্যাগগুলি অক্ষম করতে পারে (0 এ সেট করে), বা সহজভাবে নয় রেন্ডার ফ্ল্যাগগুলি প্রভাবিত করে (সেট করা নেই), এটি representচ্ছিকভাবে এটি উপস্থাপনের একটি পরিষ্কার উপায়।

স্পষ্টত কোনও ইন্টির একটি পয়েন্টার, উদাহরণস্বরূপ, লক্ষ্য অর্জন করতে পারে বা আরও ভাল, একটি ভাগ পয়েন্টার হিসাবে এটি ক্লিনার প্রয়োগের প্রস্তাব দিতে পারে, তবে আমি এই ক্ষেত্রে কোডের স্পষ্টতা সম্পর্কে তর্ক করব। নাল কি সর্বদা "সেট না" থাকে? একটি পয়েন্টার সহ, এটি পরিষ্কার নয়, নাল আক্ষরিক অর্থ বরাদ্দ বা তৈরি করা হয়নি, যদিও এটি হতে পারে , তবুও প্রয়োজনীয়ভাবে "সেট না করা" অর্থ হতে পারে না । এটি উল্লেখ করার মতো যে কোনও পয়েন্টার প্রকাশিত হতে হবে, এবং ভাল অনুশীলনে 0 তে সেট করা হয়েছে, তবে, ভাগ করা পয়েন্টারটির মতো একটি alচ্ছিককে সুস্পষ্ট পরিষ্কারের প্রয়োজন হয় না, তাই পরিষ্কারের সাথে মিশ্রণের কোনও উদ্বেগ নেই isn't alচ্ছিক সেট করা হয়নি।

আমি বিশ্বাস করি এটি কোডের স্পষ্টতা সম্পর্কে। স্পষ্টতা কোড রক্ষণাবেক্ষণ এবং উন্নয়নের ব্যয় হ্রাস করে। কোড উদ্দেশ্য সম্পর্কে একটি পরিষ্কার বোঝা অবিশ্বাস্যভাবে মূল্যবান।

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

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