আমি আজই এই চাকাটি পুনরায় উদ্ভাবন করেছি এবং ভেবেছিলাম আমি এটি ভাগ করব।
এই প্রয়োগের ক্ষেত্রে কোডগুলিতে ধ্রুবককে সংজ্ঞায়িত করে এমন কোনও পরিবর্তন প্রয়োজন হয় না , যা গণনা বা #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;
}
}