le Wednesday 22 December 2004 17:25, dimerman@netvision.net.il écrivit :
Foster, Gareth wrote:
Could you do Logger<DBG> MyLogger; MyLogger.print(); ?
It wont have the same effect, for if I parametrize the class itself, I will end up having as many actual instances as severity levels. Parametrizing the print function allows me to use the same logger (with its corresponding devices such as files, console, etc.) for different levels. Since the actual function to be called is resolved at compile time, I get to avoid costly constructions (mostly string concatenation and such) for debug purposes to be carried in the release version (assuming the compiler notices...).
what about you put the dbg-level dependant code in the formatter object, like : // a no-op formatter object : // (formatting, and outputting, is a no-op at compile-time) struct dummy_format { template<class T> dummy_format& operator%(const T& x) { return *this; } } inline ostream& operator<<(ostrem& os, dummy_format const& x) { return os; } // a level-based selecter : template<int> struct DbgFormatType { typedef boost::format type; } template<> struct DbgFormat<0> { typedef dummy_format type; } // a level-dependant formatter : template<int n> struct DbgFormat { typedef typename DbgFormatType<n>::type type; type fmter; DbgFormat(const char* s) : fmter(s) {} template<class T> type operator%(const T & x) const { return fmter % x; } } And in the code you'd do : (assuming the function dest() returns an ostream. any other semantics for output would work..) myLogger.dest() << DbgFormat<level>(fmt_str) % x1 % x2 % "truc"; if you want to put all log-related stuff (destination AND formatting policy) into a signle logger object, you could have : template<int n> class MyLogger { .. DbgFormat<n> fmter(const char* s) { return DbgFormat<n>(s); } ... } and then do : myLogger.dest() << myLogger.fmter(fmt_str) % x1 % x2 % "truc"; Would that be fitting your needs ? -- Samuel