Elegant solution from jsmith (I wouldn't have thought of some details), but I have to mention something.
Using define before including a header file to parametrize its content is not a very good affair. If header A.h depends on B.h, and includes B.h with certain defines present at the time, and then some source file includes A.h and then B.h with other defines present at that time, the result is that the latter setup is ignored, because the multiple inclusion protection of B.h kicks in.
This means that in all cases you will have to make the defines global for the entire project - by feeding them from the command line, or with implicit header file (I think that gcc supports this ). And if the options are global, then they will influence the implementation files (.cpp) as well as the header files, and there is no problem with changing the method definitions in the implementation files directly.
If you want to keep the possibility to use different setups for different sources and still allow multiple inclusion, you can either have policy that the option should be only controlled at the start of the implementation files, or do smth like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
// File: Log.h
#ifndef LOG_H
#define LOG_H
class NoLog {
public:
inline NoLog() {}
inline ~NoLog() {}
inline void AddStream( std::ostream& ) {}
inline void AddStream( const std::string& ) {}
inline void Write( const std::string& ) {}
};
class DoLog {
public:
DoLog();
~DoLog();
void AddStream( std::ostream& );
void AddStream( const std::string& );
void Write( const std::string& );
};
#endif
#ifdef NO_LOG
#define Log NoLog
#else
#define Log DoLog
#endif
|
Not a very nice solution, because Log becomes a preprocessor macro. Alternatively, you can try not to rely on the preprocessor and expose template class to the user instead.
Regards
EDIT: Bummer - one endif went at the wrong place.