टीएल; डीआर: क्या निम्नलिखित हमेशा सुरक्षित है? या क्या यह अपरिभाषित, अनिर्दिष्ट या कार्यान्वयन परिभाषित व्यवहार का कारण बनता है?क्या मैं हमेशा एक निश्चित (स्कॉप्ड) गणना के अंतर्निहित प्रकार में सुरक्षित रूप से डाल सकता हूं?
template <class T>
using ut = typename std::underlying_type<T>::type;
template <typename E> ut<E> identity(ut<E> value) {
return static_cast<ut<E>>(static_cast<E>(value));
}
अगर मैं एक scoped गणन है मैं हमेशा अंतर्निहित इसे टाइप कास्ट कर सकते हैं:
#include <cassert> // if you want to follow along
#include <initializer_list> // copy everything and remove my text
enum class priority : int {
low = 0,
normal = 1,
high = 2
};
// works fine
int example = static_cast<int>(priority::high);
सभी मूल्यों कि गणन में परिभाषित कर रहे हैं के लिए मैं भी उम्मीद कर सकते हैं कि मैं मिल वापस मूल्य:
constexpr priority identity_witness(priority p) {
return static_cast<priority>(static_cast<int>(p));
}
void test_enum() {
for (const auto p : {priority::low, priority::normal, priority::high}) {
assert(p == identity_witness(p));
}
}
N3337 के अनुसार (सी ++ 11), 5.2.9 स्टेटिक डाली [expr.static.cast] § 9-10 इस पंख है ई:
- एक दायरे वाला गणना प्रकार (7.2) का मान स्पष्ट रूप से एक अभिन्न प्रकार में बदला जा सकता। यदि मूल मान निर्दिष्ट प्रकार से प्रदर्शित किया जा सकता है तो मान अपरिवर्तित है। ...
- अभिन्न या गणना प्रकार का एक मूल्य स्पष्ट रूप से एक गणना प्रकार में परिवर्तित किया जा सकता है। मान मूल रूप से गणना मूल्यों (7.2) की सीमा के भीतर है, तो मान अपरिवर्तित है। ...
हालांकि, मैं इसका उल्टा में दिलचस्पी रखता हूँ। क्या होता है अगर मैं एक enum और वापस अंतर्निहित प्रकार पर डाल दिया?
constexpr int identity_witness(int i) {
return static_cast<int>(static_cast<priority>(i));
}
void test_int() {
for (const auto p : {0, 1, 2, 3, 4, 5}) {
assert(p == identity_witness(p));
}
}
int main() {
test_enum();
test_int();
}
यह संकलित करता है तथा ठीक काम करता है, के बाद से अंतर्निहित प्रकार के लिए एक static_cast
बिल्कुल (शायद) स्मृति परिवर्तन नहीं होगा। हालांकि, मानक का कहना है कि व्यवहार अनिर्दिष्ट है यदि मूल्य श्रेणी में नहीं है:
- [जारी रखा] अन्यथा, जिसके परिणामस्वरूप मूल्य अनिर्दिष्ट है (और में नहीं हो सकता है वह सीमा)।
रेंज enumerations के मेरे लिए स्पष्ट नहीं है। 7.2§7 के मुताबिक, "गणना के मूल्य अंतर्निहित प्रकार के मूल्य हैं" यदि गणना के अंतर्निहित प्रकार को ठीक किया गया है। इसलिए, किसी भी std::underlying_type<my_enumeration_type>
के लिए, उपरोक्त संपत्ति को पकड़ना चाहिए।
क्या यह तर्क मानक में कुछ अजीब खंड को याद करता है, या गणना के अंतर्निहित प्रकार में एक कलाकार को अपरिभाषित या अनिर्दिष्ट व्यवहार का कारण बन सकता है?
अच्छा सवाल, और मुझे उम्मीद है कि उत्तर 'हां हमेशा सुरक्षित' है क्योंकि मैं थोड़ी देर के लिए अंतर्निहित प्रकार पर सहायक कास्टिंग का उपयोग कर रहा हूं, इसे और अधिक विचार किए बिना: पी –
stijn
@stijn तो करें मैं, एक ही उपयोग के मामले के साथ। यह सिर्फ एक कोड समीक्षा के दौरान आया था। 7.2 और 5.2.9 के अनुसार, यह _should_ ठीक हो जाएगा, लेकिन मैं किसी और द्वारा दूसरी राय प्राप्त करना चाहता हूं (या अगले हफ्ते के अंत में मानक फिर से पढ़ना)। – Zeta