আপনি যদি এনাম ক্লাসে অবৈধ মান স্থির_কাস্ট করেন তবে কি হবে?


146

এই সি ++ 11 কোডটি বিবেচনা করুন:

enum class Color : char { red = 0x1, yellow = 0x2 }
// ...
char *data = ReadFile();
Color color = static_cast<Color>(data[0]);

ধরুন যে ডেটা [0] আসলে 100 টি the মান অনুসারে রঙটি কী সেট করা হয়? বিশেষত, যদি আমি পরে করি

switch (color) {
    // ... red and yellow cases omitted
    default:
        // handle error
        break;
}

মানক গ্যারান্টি দেয় যে ডিফল্ট আঘাত করা হবে? যদি তা না হয় তবে এখানে ত্রুটিটি পরীক্ষা করার উপযুক্ত, সবচেয়ে দক্ষ, সবচেয়ে মার্জিত উপায় কী?

সম্পাদনা করুন:

বোনাস হিসাবে, স্ট্যান্ডার্ড কি এই বিষয়ে তবে কোনও সরল এনামের সাথে কোনও গ্যারান্টি দেয়?

উত্তর:


131

মান অনুযায়ী রঙ সেট কি?

সি ++ 11 এবং সি ++ 14 স্ট্যান্ডার্ডের একটি উদ্ধৃতি দিয়ে উত্তর:

[Expr.static.cast] / 10

অবিচ্ছেদ্য বা গণনা প্রকারের একটি মান সুস্পষ্টভাবে একটি গণনা প্রকারে রূপান্তরিত হতে পারে। মূল মান গণনা মানের (7.2) এর সীমার মধ্যে থাকলে মানটি অপরিবর্তিত থাকে। অন্যথায়, ফলস্বরূপ মানটি অনির্ধারিত (এবং সেই সীমাতে নাও থাকতে পারে)।

আসুন গণনার মানগুলির ব্যাপ্তিটি সন্ধান করা যাক : [dcl.enum] / 7

এমন একটি গণনার জন্য যার অন্তর্নিহিত প্রকারটি স্থির রয়েছে, গণনার মানগুলি অন্তর্নিহিত প্রকারের মান।

সিডাব্লুজি 1766 এর আগে (সি ++ 11, সি ++ 14) সুতরাং, এর জন্য data[0] == 100, ফলাফলটির মান নির্দিষ্ট করা হয় (*), এবং কোনও অপরিজ্ঞাত আচরণ (ইউবি) জড়িত থাকে না। আরও সাধারণভাবে, আপনি অন্তর্নিহিত টাইপ থেকে অঙ্কের প্রকারে যেমন কাস্ট করেন, তেমন কোনও মানই এর data[0]জন্য ইউবি বাড়ে না static_cast

ফিটনেসে 1766 (সি ++ 17) পর দেখুন ফিটনেসে 1766 পালাতে পারে । [Expr.static.cast] পি 10 অনুচ্ছেদটি শক্তিশালী করা হয়েছে, তাই আপনি এখন ইউবিতে আবেদন করতে পারেন যদি আপনি এনুমের প্রকারের জন্য এনামের উপস্থাপনযোগ্য সীমার বাইরে থাকা কোনও মান ফেলে দেন। এটি এখনও প্রশ্নের দৃশ্যে প্রযোজ্য নয়, যেহেতু data[0]গণনার অন্তর্নিহিত ধরণের (উপরে দেখুন)।

দয়া করে নোট করুন যে CWG 1766 স্ট্যান্ডার্ডটিতে একটি ত্রুটি হিসাবে বিবেচিত হয়, তাই সংকলক প্রয়োগকারীরা তাদের সি ++ 11 এবং সি ++ 14 সংকলন মোডে প্রয়োগ করার জন্য এটি গ্রহণ করা হয়।

(*) charকমপক্ষে 8 বিট প্রশস্ত হওয়া আবশ্যক, তবে এটির প্রয়োজন নেই unsigned। সর্বাধিক মান স্থিতিশীল হওয়া কমপক্ষে 127C99 স্ট্যান্ডার্ডের আনেক্সেক্স ই হওয়া আবশ্যক।


[Expr] / 4 এর সাথে তুলনা করুন

যদি কোনও অভিব্যক্তির মূল্যায়নের সময়, ফলাফলটি গাণিতিকভাবে সংজ্ঞায়িত হয় না বা এর ধরণের জন্য উপস্থাপনযোগ্য মানগুলির পরিসরে থাকে না, তবে আচরণটি অনির্ধারিত।

সিডাব্লুজি 1766 এর আগে রূপান্তর ইন্টিগ্রাল টাইপ -> গণনা টাইপ একটি অনির্ধারিত মান উত্পাদন করতে পারে । প্রশ্নটি হল: একটি অনির্ধারিত মান কি এর ধরণের জন্য উপস্থাপনযোগ্য মানগুলির বাইরে থাকতে পারে? আমি বিশ্বাস করি উত্তর হল কোন - যদি উত্তর ছিল হ্যাঁ , সেখানে গ্যারান্টী আপনার মধ্যে "এই অপারেশন একটি অনির্দিষ্ট মান উৎপন্ন" এবং "এই অপারেশন অনির্ধারিত আচরণ আছে" স্বাক্ষরিত ধরনের অপারেশনের জন্য পেতে কোনো পার্থক্য হবে না।

সুতরাং, সিডাব্লুজি 1766 এর আগে এমনকি ইউবিকেও অনুরোধ static_cast<Color>(10000)করবে না ; কিন্তু ফিটনেসে 1766 পরে, এটা করে UB ডাকা।


এখন, switchবিবৃতি:

[Stmt.switch] / 2

শর্তটি অবিচ্ছেদ্য প্রকার, গণনা প্রকার বা শ্রেণীর প্রকারের হতে পারে। [...] ইন্টিগ্রাল প্রচারগুলি করা হয়।

[Conv.prom] / 4

একটি অনিরীক্ষণযোগ্য গণনা প্রকারের একটি মূল্য যার অন্তর্নিহিত প্রকারটি নির্দিষ্ট করা (7.2) তার অন্তর্নিহিত প্রকারের একটি মূল্যে রূপান্তরিত হতে পারে। তদুপরি, যদি অবিচ্ছেদ্য প্রচারটি এর অন্তর্নিহিত ধরণের ক্ষেত্রে প্রয়োগ করা যায়, তবে একটি অনির্ধারিত গণনা প্রকারের একটি অগ্রগতি যার অন্তর্নিহিত প্রকারটি স্থির থাকে তাও প্রচারিত অন্তর্নিহিত প্রকারের মূল্যে রূপান্তরিত হতে পারে।

নোট: একটি scoped enum W / O এর অন্তর্নিহিত টাইপ enum-বেস হয় int। Unscoped enums জন্য অন্তর্নিহিত টাইপ বাস্তবায়ন-সংজ্ঞায়িত, কিন্তু চেয়ে বড় হইবে না intযদি intসব তথ্যসংগ্রহকারী মান থাকতে পারে।

একটি অনির্ধারিত গণনার জন্য , এটি আমাদেরকে / 1 এ নিয়ে যায়

একটি পূর্ণসংখ্যা ছাড়া অন্য ধরনের prvalue bool, char16_t, char32_t, অথবা wchar_tযার পূর্ণসংখ্যা রূপান্তর ক্রম (4.13) পদে চেয়ে কম হয় intধরনের prvalue রূপান্তরিত করা যেতে পারে intযদি intউৎস ধরনের সমস্ত মান উপস্থাপন করতে পারেন; অন্যথায়, উত্স মূল্যকে প্রকারের ধরণের রূপান্তরিত করা যেতে পারে unsigned int

একটি অপ্রকাশিত গণনার ক্ষেত্রে আমরা intএখানে এর সাথে কাজ করব। জন্য বিশ্লেষণ করা enumerations ( enum classএবং enum struct), কোন অবিচ্ছেদ্য প্রচার প্রযোজ্য। যে কোনও উপায়ে, অবিচ্ছেদ্য প্রচার কোনওভাবে ইউবির দিকে পরিচালিত করে না, কারণ সঞ্চিত মান অন্তর্নিহিত ধরণের এবং এর পরিসীমাতে থাকে int

[Stmt.switch] / 5

যখন switchবিবৃতি মৃত্যুদন্ড কার্যকর করা হয়, তার অবস্থা মূল্যায়ন এবং প্রতিটি ক্ষেত্রে ধ্রুবক সঙ্গে তুলনা করা হয়। যদি কেস কনস্ট্যান্টগুলির একটি শর্তের মানের সমান হয় তবে ম্যাচযুক্ত caseলেবেলের পরে স্টেটমেন্টে নিয়ন্ত্রণ সরবরাহ করা হবে । যদি কোনও caseধ্রুবক শর্তটির সাথে মেলে না, এবং যদি কোনও defaultলেবেল থাকে তবে নিয়ন্ত্রণটি লেবেলযুক্ত লেবেলযুক্ত বিবৃতিতে চলে যায় default

defaultট্যাগ আঘাত করতে হবে।

দ্রষ্টব্য: তুলনা অপারেটরটির জন্য অন্য কেউ নজর দিতে পারে তবে উল্লেখ করা "তুলনা" তে এটি স্পষ্টভাবে ব্যবহৃত হয় না। প্রকৃতপক্ষে, আমাদের ক্ষেত্রে স্কোপড বা অপরিশোধিত এনামগুলির জন্য এটি ইউবি প্রবর্তন করার কোনও ইঙ্গিত নেই।


বোনাস হিসাবে, স্ট্যান্ডার্ড কি এই বিষয়ে তবে কোনও সরল এনামের সাথে কোনও গ্যারান্টি দেয়?

enumস্কোপযুক্ত কিনা তা এখানে কোনও পার্থক্য করে না। তবে অন্তর্নিহিত ধরণটি স্থির কিনা তা কোনও পার্থক্য করে। সম্পূর্ণ [decl.enum] / 7 হ'ল:

এমন একটি গণনার জন্য যার অন্তর্নিহিত প্রকারটি স্থির রয়েছে, গণনার মানগুলি অন্তর্নিহিত প্রকারের মান। অন্যথা, শুমার যেখানে জন্য মিনিট ক্ষুদ্রতম গণনাকারী এবং সর্বোচ্চ বৃহত্তম, শুমার মান মান সীমার মধ্যে হয় মিনিট থেকে b সর্বোচ্চ , সংজ্ঞায়িত নিম্নরূপ: আসুন Kহতে 1দুই এর সম্পূরক প্রতিনিধিত্ব এবং 0একটি জন্য কারও পরিপূরক বা সাইন-বিশালতার প্রতিনিধিত্ব। সর্বোচ্চ চেয়ে ক্ষুদ্রতম মান বেশী বা সমান সর্বোচ্চ (| ই মিনিট | - K, | ই সর্বোচ্চ |) এবং সমান 2এম - 1 , যেখানেMএকটি অ-নেতিবাচক পূর্ণসংখ্যা। বি মিনিট শূন্য হয় যদিমিনিট অ-নেতিবাচক হয় এবং - (বি সর্বোচ্চ + K) অন্যথায়।

আসুন নীচের গণনাটি একবার দেখুন:

enum ColorUnfixed /* no fixed underlying type */
{
    red = 0x1,
    yellow = 0x2
}

নোট করুন যে আমরা এটিকে একটি স্কোপড এনাম হিসাবে সংজ্ঞায়িত করতে পারি না, যেহেতু সমস্ত স্কোপড এনামগুলিতে অন্তর্নিহিত প্রকারগুলি নির্দিষ্ট করা আছে।

ভাগ্যক্রমে, ColorUnfixedএর ক্ষুদ্রতম গণকটি red = 0x1, তাই সর্বোচ্চ (| ই মিনিট - K, | ই সর্বোচ্চ |) | ই সর্বোচ্চ | এর সমান যে কোনও ক্ষেত্রে, যা হয় yellow = 0x2। ক্ষুদ্রতম মানটি বৃহত্তর বা সমান 2, যা ধনাত্মক পূর্ণসংখ্যার জন্য 2 এম - 1 এর সমান Mহয় 3( 2 2 - 1 )। (আমার ধারণা অভিপ্রায় 1-বিট-পদক্ষেপে পরিমাণে পরিসীমা অনুমতি দেওয়া।) এটা যে অনুসরণ সর্বোচ্চ হয় 3এবং bmin হয় 0

সুতরাং, 100এর সীমার বাইরে থাকবে ColorUnfixedএবং static_castসিডাব্লুজি 1766 এর আগে একটি অনির্ধারিত মান এবং সিডাব্লুজি 1766 এর পরে অপরিজ্ঞাত আচরণ করবে।


3
অন্তর্নিহিত প্রকারটি ঠিক করা হয়েছে, সুতরাং গণনা মানগুলির পরিসীমা (§7.2 [dcl.enum] p7) "অন্তর্নিহিত ধরণের মান"। 100 অবশ্যই একটি মান char, সুতরাং "যদি মূল মানটি গণনা মানের (7.2) এর সীমার মধ্যে থাকে তবে মানটি অপরিবর্তিত থাকে।" প্রযোজ্য।
কেসি

2
"ইউবি" বলতে কী বোঝায় তা খুঁজতে আমাকে অনুসন্ধান করতে হয়েছিল had ('অপরিবর্তিত আচরণ') প্রশ্নটিতে অপরিজ্ঞাত আচরণের সম্ভাবনার কথা বলা হয়নি; সুতরাং এটি আমার কাছে ঘটেনি যে আপনি সম্ভবত সে সম্পর্কে কথা বলছেন।
করাদোক

2
@ ক্যারাকডোক আমি এই শব্দটির প্রথম উপস্থিতিতে একটি লিঙ্ক যুক্ত করেছি।
ডায়প

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

1
@ রুসলান সিডাব্লুজি 1766 (বা এর রেজোলিউশন) সি ++ 14 এর অংশ নয় , তবে আমি মনে করি এটি সি ++ 17 এর অংশ হবে। এমনকি সি ++ ১ rules বিধিবিধানের সাথেও, "আপনার উত্তরের আরও পাঠ্য অবৈধ করুন" দিয়ে আপনি কী বোঝাতে চেয়েছেন তা আমি পুরোপুরি বুঝতে পারি না। আমার উত্তরের অন্যান্য অংশগুলি মূলত "গণনার মানগুলির পরিসীমা" এর সাথে সম্পর্কিত যেটি expr.static.cast p10 উল্লেখ করছে।
ডায়প
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.