आप वास्तव में इसे दोनों तरीकों से प्राप्त कर सकते हैं, यानी कोड से अनुवाद करने के लिए दो फ़ंक्शन हैं।
पाठ्यक्रम की पहली बात यह है कि #define
का उपयोग स्थिरांक के लिए नहीं किया जाना चाहिए, एक enum शायद सबसे अच्छा होगा, हालांकि एक enum विस्तारित नहीं किया जा सकता है, जिसके लिए आपकी सभी त्रुटियों को एक ही स्थान पर परिभाषित किया जाना चाहिए (ouch, धन्यवाद निर्भरताओं के लिए बहुत कुछ ...)
हालांकि आप इसे अन्य कर सकते हैं, नामों को अलग करने के लिए नामस्थानों का उपयोग करके, और पूरी पीढ़ी को संभालने के लिए प्रीप्रोकैसिंग। लुकअप भाग के लिए, हम Bimap का उपयोग करेंगे।
पहले हम एक हैंडलर वर्ग को परिभाषित करने की जरूरत है (जो भी इनलाइन के लिए आवश्यक नहीं है, लेकिन यह उदाहरण के लिए आसान है)
#include <boost/bimap.hpp>
#include <boost/optional.hpp>
namespace error
{
class Handler
{
public:
typedef boost::optional<int> return_code;
typedef boost::optional<std::string> return_description;
static bool Register(int code, const char* description)
{
typedef error_map::value_type value_type;
bool result = MMap().insert(value_type(code,description)).second;
// assert(result && description)
return result;
}
static return_code GetCode(std::string const& desc)
{
error_map::map_by<description>::const_iterator it
= MMap().by<description>().find(desc);
if (it != MMap().by<description>().end()) return it->second;
else return return_code();
}
static return_description GetDescription(int c)
{
error_map::map_by<code>::const_iterator it
= MMap().by<code>().find(c);
if (it != MMap().by<code>().end()) return it->second;
else return return_description();
}
typedef std::vector< std::pair<int,std::string> > errors_t;
static errors_t GetAll()
{
errors_t result;
std::for_each(MMap().left.begin(), MMap().left.end(),
result.push_back(boost::lambda::_1));
return result;
}
private:
struct code {};
struct description {};
typedef boost::bimap<
boost::tagged<int, code>,
boost::tagged<std::string, description>
> error_map;
static error_map& Map() { static error_map MMap; return MMap; }
};
// Short-Hand
boost::optional<int> GetCode(std::string const& d)
{
return Handler::GetCode(d);
}
boost::optional<std::string> GetDescription(int c)
{
return Handler::GetDescription(c);
}
} // namespace error
तो हम बस कुछ वाक्यात्मक चीनी उपलब्ध कराने की आवश्यकता:
#define DEFINE_NEW_ERROR(Code_, Description_) \
const int Description_ = Code_; \
namespace error { \
const bool Description##_Registered = \
::error::Handler::Register(Code_, #Description_); \
}
अज्ञात त्रुटि के पंजीकरण के मामले में हम थोड़ा अधिक हिंसक हो सकते हैं (उदाहरण के लिए जोर दें)।
और फिर हम हमेशा उस मैक्रो को उसमें लपेट सकते हैं जो एक से अधिक प्रतीकों को परिभाषित कर सकता है ... लेकिन यह एक अभ्यास के रूप में छोड़ा गया है।
उपयोग:
// someErrors.hpp
#include "error/handler.hpp"
DEFINE_NEW_ERROR(1, AnError)
DEFINE_NEW_ERROR(2, AnotherError)
// someFile.cpp
#include <iostream>
#include "error/handler.hpp"
int main(int argc, char* argv[])
{
int code = 6;
boost::optional<std::string> desc = error::GetDescription(code);
if (desc)
{
std::cout << "Code " << code << " is mapped to <" << *desc << ">" << std::endl;
}
else
{
std::cout << "Code " << code << " is unknown, here is the list:\n";
::error::Handler::errors_t errors = ::Error::Handler::GetAll();
std::for_each(errors.begin(), errors.end(), std::cout << " " << _1);
std::cout << std::endl;
}
}
अस्वीकरण: मैं लैम्ब्डा सिंटैक्स के बारे में भी यकीन नहीं है, लेकिन यह लेखन को सरल बनाया था।
क्षमा करें, मुझे कुछ जवाब देखने के बाद एक परिशिष्ट बनाना चाहिए: मैं जो करने में सक्षम होना चाहता हूं वह वास्तव में उन स्ट्रिंग्स की सूची संकलित करने और उसमें अनुक्रमणित करने के लिए उत्पन्न होता है। – brandonC
का डुप्लिकेट: http://stackoverflow.com/questions/2571816/is-it-possible-to-define-enumalpha –