c++ testing printing

c++ - Imprimir información en "modo de prueba" pero no en "ejecución normal"



testing printing (3)

La solución del preprocesador funcionará, pero puede ser molesto tener que reconstruir para cambiar de una a la otra. A menudo tomaré la decisión en tiempo de ejecución. Primero declaro:

static void do_nothing(const char *fmt, ...) { (void)fmt; } extern void real_dprintf(const char *fmt, ...); void (*dprintf)(const char *fmt, ...) = do_nothing;

Luego en el código de inicialización tengo

if (getenv("APPLICATION") && strstr(getenv("APPLICATION"), "dprintf")) dprintf = real_dprintf;

De esta forma, puedo cambiar modos rápidamente cambiando el valor de una variable de entorno.

Estoy usando una aplicación en c ++ que usa una función dprintf especial para imprimir información, este es un ejemplo:

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

Lo que ocurre es que cuando defino verbose para propósitos de prueba, imprimo la información y cuando estoy trabajando en ejecución normal no la defino y no veo información inútil en la pantalla. Mi pregunta es ¿cómo puedo hacer esa función o implementar la misma idea ?.


#ifdef DEBUG #define dprintf(format, ...) real_dprintf(format, __VA_ARGS__) #else #define dprintf #endif

Aquí, real_dprintf () es la función "real" que se invoca, y dprintf () es simplemente una macro que envuelve la llamada.


Intento evitar usar las funciones var-arg c-style por dos razones principales:

  • No son de tipo seguro, no pueden usar el operador <<
  • No reconocen cuando se proporcionaron muy pocos o muchos argumentos

Hice una forma que funciona con boost::fusion , que se da argumentos de una manera segura. Se repite sobre esos argumentos, imprimiéndolos cuando se encuentra un % . Si se dieron demasiados o demasiados argumentos, se lanza una excepción.

Todavía hay un problema: las macros variadas aún no son estándar en C ++. Entonces, he hecho dos versiones. Uno que funciona con C ++ actual. Tienes que invocarlo usando

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

Entonces. La otra versión, que utiliza macros variadic, se puede usar definiendo un símbolo preprocesador, que le permite escribir

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

Aquí está el código. El boost.fusion proporciona más detalles para esto:

#include <boost/fusion/include/sequence.hpp> #include <boost/fusion/include/make_vector.hpp> #include <boost/fusion/include/next.hpp> #include <stdexcept> #include <iostream> template<typename IterS, typename IterSeqE> 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<typename IterS, typename IterSeqB, typename IterSeqE> 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<typename Seq> 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)); }