मैंने आज ही इस पहिये का फिर से आविष्कार किया, और सोचा कि मैं इसे साझा करूँगा।
इस कार्यान्वयन के लिए स्थिरांक को परिभाषित करने वाले कोड में किसी भी बदलाव की आवश्यकता नहीं होती है, जो एन्यूमरेशन या #defineएस या कुछ और हो सकता है जो किसी पूर्णांक के लिए समर्पित होता है - मेरे मामले में मेरे पास अन्य प्रतीकों के संदर्भ में परिभाषित चिह्न थे। यह विरल मूल्यों के साथ भी अच्छा काम करता है। यहां तक कि यह एक ही मूल्य के लिए कई नामों की अनुमति देता है, पहले वाला हमेशा लौटाता है। केवल नकारात्मक पक्ष यह है कि आपको स्थिरांक की एक तालिका बनाने की आवश्यकता होती है, जो बाहर हो सकती है क्योंकि उदाहरण के लिए नए जोड़े जाते हैं।
struct IdAndName
{
int id;
const char * name;
bool operator<(const IdAndName &rhs) const { return id < rhs.id; }
};
#define ID_AND_NAME(x) { x, #x }
const char * IdToName(int id, IdAndName *table_begin, IdAndName *table_end)
{
if ((table_end - table_begin) > 1 && table_begin[0].id > table_begin[1].id)
std::stable_sort(table_begin, table_end);
IdAndName searchee = { id, NULL };
IdAndName *p = std::lower_bound(table_begin, table_end, searchee);
return (p == table_end || p->id != id) ? NULL : p->name;
}
template<int N>
const char * IdToName(int id, IdAndName (&table)[N])
{
return IdToName(id, &table[0], &table[N]);
}
आप इसका उपयोग कैसे करेंगे इसका एक उदाहरण:
static IdAndName WindowsErrorTable[] =
{
ID_AND_NAME(INT_MAX), // flag value to indicate unsorted table
ID_AND_NAME(NO_ERROR),
ID_AND_NAME(ERROR_INVALID_FUNCTION),
ID_AND_NAME(ERROR_FILE_NOT_FOUND),
ID_AND_NAME(ERROR_PATH_NOT_FOUND),
ID_AND_NAME(ERROR_TOO_MANY_OPEN_FILES),
ID_AND_NAME(ERROR_ACCESS_DENIED),
ID_AND_NAME(ERROR_INVALID_HANDLE),
ID_AND_NAME(ERROR_ARENA_TRASHED),
ID_AND_NAME(ERROR_NOT_ENOUGH_MEMORY),
ID_AND_NAME(ERROR_INVALID_BLOCK),
ID_AND_NAME(ERROR_BAD_ENVIRONMENT),
ID_AND_NAME(ERROR_BAD_FORMAT),
ID_AND_NAME(ERROR_INVALID_ACCESS),
ID_AND_NAME(ERROR_INVALID_DATA),
ID_AND_NAME(ERROR_INVALID_DRIVE),
ID_AND_NAME(ERROR_CURRENT_DIRECTORY),
ID_AND_NAME(ERROR_NOT_SAME_DEVICE),
ID_AND_NAME(ERROR_NO_MORE_FILES)
};
const char * error_name = IdToName(GetLastError(), WindowsErrorTable);
IdToNameसमारोह पर निर्भर करता हैstd::lower_bound जल्दी लुकअप, जो मेज अनुसार क्रमबद्ध करने की आवश्यकता है क्या करना है। यदि तालिका की पहली दो प्रविष्टियां क्रम से बाहर हैं, तो फ़ंक्शन इसे स्वचालित रूप से सॉर्ट करेगा।
संपादित करें: एक टिप्पणी ने मुझे उसी सिद्धांत का उपयोग करने के दूसरे तरीके के बारे में सोचा। एक मैक्रो एक बड़े switchबयान की पीढ़ी को सरल करता है ।
#define ID_AND_NAME(x) case x: return #x
const char * WindowsErrorToName(int id)
{
switch(id)
{
ID_AND_NAME(ERROR_INVALID_FUNCTION);
ID_AND_NAME(ERROR_FILE_NOT_FOUND);
ID_AND_NAME(ERROR_PATH_NOT_FOUND);
ID_AND_NAME(ERROR_TOO_MANY_OPEN_FILES);
ID_AND_NAME(ERROR_ACCESS_DENIED);
ID_AND_NAME(ERROR_INVALID_HANDLE);
ID_AND_NAME(ERROR_ARENA_TRASHED);
ID_AND_NAME(ERROR_NOT_ENOUGH_MEMORY);
ID_AND_NAME(ERROR_INVALID_BLOCK);
ID_AND_NAME(ERROR_BAD_ENVIRONMENT);
ID_AND_NAME(ERROR_BAD_FORMAT);
ID_AND_NAME(ERROR_INVALID_ACCESS);
ID_AND_NAME(ERROR_INVALID_DATA);
ID_AND_NAME(ERROR_INVALID_DRIVE);
ID_AND_NAME(ERROR_CURRENT_DIRECTORY);
ID_AND_NAME(ERROR_NOT_SAME_DEVICE);
ID_AND_NAME(ERROR_NO_MORE_FILES);
default: return NULL;
}
}