doctest

FORK: The fastest feature-rich C++11/14/17/20 single-header testing framework
git clone https://git.neptards.moe/neptards/doctest.git
Log | Files | Refs | README

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 }