how_exception_translators_work.cpp (1910B)
1 #include <vector> 2 #include <iostream> 3 #include <stdexcept> 4 using namespace std; 5 6 #define CAT_IMPL(s1, s2) s1##s2 7 #define CAT(s1, s2) CAT_IMPL(s1, s2) 8 #define ANONYMOUS(x) CAT(x, __COUNTER__) 9 10 struct ITranslator { 11 virtual bool translate(string&) = 0; 12 }; 13 14 template<typename T> 15 struct Translator : ITranslator { 16 Translator(string(*func)(T)) : m_func(func) {} 17 18 bool translate(string& res) { 19 try { 20 throw; 21 } catch(T ex) { 22 res = m_func(ex); 23 return true; 24 } catch(...) { 25 return false; 26 } 27 } 28 29 string(*m_func)(T); 30 }; 31 32 void regTranslatorImpl(ITranslator* t); // fwd decl 33 34 template<typename T> 35 int regTranslator(string(*func)(T)) { 36 static Translator<T> t(func); 37 regTranslatorImpl(&t); 38 return 0; 39 } 40 41 #define REG_TRANSLATOR_2(name, type) \ 42 static string name(type); \ 43 static int ANONYMOUS(TRANS_) = regTranslator(&name); \ 44 static string name(type) 45 46 #define REG_TRANSLATOR(type) REG_TRANSLATOR_2(ANONYMOUS(TRANS_), type) 47 48 // impl 49 50 vector<ITranslator*> translators; 51 52 void regTranslatorImpl(ITranslator* t) { 53 translators.push_back(t); 54 } 55 56 string translate() { 57 // try translators 58 string res; 59 for(size_t i = 0; i < translators.size(); ++i) 60 if(translators[i]->translate(res)) 61 return res; 62 // proceed with default translation 63 try { 64 throw; 65 } catch(exception& ex) { 66 return ex.what(); 67 } catch(string& msg) { 68 return msg; 69 } catch(const char* msg) { 70 return msg; 71 } catch(...) { 72 return "Unknown exception!"; 73 } 74 } 75 76 // usage 77 78 REG_TRANSLATOR(double& e) { 79 return string("double: ") + to_string(e); 80 } 81 82 int main() { 83 try { 84 //throw 42; 85 throw 5.0; 86 //throw runtime_error("whops!"); 87 } catch(...) { 88 cout << translate() << endl; 89 } 90 }