简体   繁体   中英

C++ alternative to pre-processor #ifdef / #endif

I have a StopWatch class which I use to measure execution time. I instantiate several different stopwatches to log execution time by category. For example:

#ifdef EXEC_TIME_PROF
StopWatch func1sw;
StopWatch func2sw;
#endif

void foo() {
#ifdef EXEC_TIME_PROF
func1sw.start();
#endif

func1();

#ifdef EXEC_TIME_PROF
func1sw.stop();
func2sw.start();
#endif

func2();

#ifdef EXEC_TIME_PROF
func2sw.stop();
#endif
}

#ifdef EXEC_TIME_PROF
func1sw.logTime();
func2sw.logTime();
#endif

So the actual 2-line function becomes a lot longer and more cluttered with all the #ifdef statements. The reason that I use the #ifdef is because I don't want the statements to be compiled in a non-profiling / production build. Does anyone know a better way of doing this? My development environment is Windows / Visual Studio C++ 2015.

You can just use the macro to switch between a class that does something and a class that does nothing at all. The compiler should recognize that and exclude it from compilation.

#ifdef EXEC_TIME_PROF

// your actual implementation
class StopWatch
{
    // ...
};

#else

// completely empty implementation
class StopWatch
{
public:
    void start() {}
    void stop() {}
    void logTime() {}
};

#endif

If you still want to use StopWatch for other things in production, then just use something else like ProfilingStopWatch roughly as follows:

#ifdef EXEC_TIME_PROF

typedef StopWatch ProfilingStopWatch;

#else

// completely empty implementation
class ProfilingStopWatch
{
public:
    void start() {}
    void stop() {}
    void logTime() {}
};

#endif

So, in case it's not completely clear, you can remove the other macro tests from your code and use the class normally:

ProfilingStopWatch func1sw;
ProfilingStopWatch func2sw;

void foo()
{
    func1sw.start();
    func1();
    func1sw.stop();

    func2sw.start();
    func2();
    func2sw.stop();
}

func1sw.logTime();
func2sw.logTime();

Simply add some extra macros to wrap the stopwatches, eg:

#define concat(a,b) a ## b

#ifdef EXEC_TIME_PROF
StopWatch func1sw;
StopWatch func2sw;

#define RUN_FUNC(funcName) \
    concat(funcName,sw).start(); \
    funcName(); \
    concat(funcName,sw).stop();

#else

#define RUN_FUNC(funcName) \
    funcName();

#endif

void foo() {
     RUN_FUNC(func1);
     RUN_FUNC(func2);
}

#ifdef EXEC_TIME_PROF
func1sw.logTime();
func2sw.logTime();
#endif

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM