Print information in “test mode” but not in “normal execution”

后端 未结 3 1691
没有蜡笔的小新
没有蜡笔的小新 2020-12-16 05:50

I am using an application in c++ that uses a special dprintf function to print information, this is an example:

dprintf(verbose, \"The value is: %d\", i);
         


        
3条回答
  •  Happy的楠姐
    2020-12-16 06:31

    I try to avoid using var-arg c-style functions for two main reasons:

    • They are not type-safe, can't use operator<<
    • They don't recognize when too few or many arguments were provided

    I've made a way that works using boost::fusion, which is given arguments in a type-safe way. It iterates over those arguments, printing out them when a % is encountered. If too few or too many arguments were given, an exception is thrown.

    There is one problem still: Variadic macros are not yet standard in C++. So, i have made two versions. One that work with current C++. You have to invoke it using

    dprintf("name: %, value: %\n", ("foo", 42));
    

    Then. The other version, using variadic macros, can be used by defining a preprocessor symbol, which enables you to write

    dprintf("name: %, value: %\n", "foo", 42);
    

    Here is the code. The boost.fusion provides more details for this:

    #include 
    #include 
    #include 
    #include 
    #include 
    
    template
    void print_vec(IterS b, IterS e, IterSeqE, IterSeqE) {
        while(b != e) {
            if(*b == '%') {
                if(++b != e && *b == '%') {
                    std::cout << '%';
                } else {
                    throw std::invalid_argument("too many '%'");
                }
            } else {
                std::cout << *b;
            }
            ++b;
        }
    }
    
    template
    void print_vec(IterS b, IterS e, IterSeqB seqb, IterSeqE seqe) {
        while(b != e) {
            if(*b == '%') {
                if(++b != e && *b == '%') {
                    std::cout << '%';
                } else {
                    std::cout << *seqb;
                    return print_vec(b, e, next(seqb), seqe);
                }
            } else {
                std::cout << *b;
            }
            ++b;
        }
        throw std::invalid_argument("too few '%'");
    }
    
    template
    void print_vec(std::string const& msg, Seq const& seq) {
        print_vec(msg.begin(), msg.end(), begin(seq), end(seq));
    }
    
    #ifdef USE_VARIADIC_MACRO
    #  ifdef DEBUG
    #    define dprintf(format, ...) \
             print_vec(format, boost::fusion::make_vector(__VA_ARGS__))
    #  else 
    #    define dprintf(format, ...)
    #  endif
    #else
    #  ifdef DEBUG
    #    define dprintf(format, args) \
             print_vec(format, boost::fusion::make_vector args)
    #  else 
    #    define dprintf(format, args)
    #  endif
    #endif
    
    // test, using the compatible version. 
    int main() {
        dprintf("hello %, i'm % years old\n", ("litb", 22));
    }
    

提交回复
热议问题