How to write a c++ assert macro with a varying number of informational arguments?

后端 未结 5 1513
情深已故
情深已故 2021-01-14 15:09

I am trying to write a macro dbgassert similar to the standard assert. In addition to what assert does, I want to dbgassert

5条回答
  •  鱼传尺愫
    2021-01-14 15:43

    Just as a note, I was able to figure out another means to solve the trailing comma issue, in addition to @cmaster and @ds27680's solution. Since having __VA_ARGS__ leads to an extra comma, I can pack __VA_ARGS__ into a std::tuple or a function call, and use the tuple/result as a parameter of the real function. Now empty __VA_ARGS__'s won't be a problem because its packed into one valid value (i.e. either an empty tuple or the return value of a nullary function). I guess this is longer in code, but a bit more portable without involving ##.

    The above two cases are shown in the dbgassert and dbgassert1 macros in the code below, respectively.

    #include 
    #include 
    #include 
    using namespace std;
    
    template 
    string print_tuple(tuple tp) {
      return ""; //print the tuple...
    }
    
    template 
    void realdbgassert(tuple info,const char *msg, const char *file, int line) {
      cout << "Assertion failed! \nFile " << file << ", Line " << line << endl 
           << "  Expression: " << msg << endl
           << "  Info: " << print_tuple(info) << endl;
      std::abort();
    }
    
    #define dbgassert(EX,...) \
      (void)((EX) || (realdbgassert (std::tie(__VA_ARGS__),#EX,__FILE__, __LINE__),0))
    
    void realdbgassert1(string info,const char *msg, const char *file, int line) {
      cout << "Assertion failed! \nFile " << file << ", Line " << line << endl 
           << "  Expression: " << msg << endl
           << "  Info: " << info << endl;
      std::abort();
    }
    
    template 
    string print_info(Args ... args) {
      return "";  //print stuff
    }
    
    #define dbgassert1(EX,...) \
      (void)((EX) || (realdbgassert1 (print_info(__VA_ARGS__),#EX,__FILE__, __LINE__),0))
    
    
    int main() {
      dbgassert(1>2,"right","yes"); //OK
      dbgassert(1>2,"right"); //OK
      dbgassert(1>2); //OK now
      dbgassert1(1>2); //OK too
    }
    

提交回复
热议问题