Вы можете использовать определение друга, которое определит оператор в окружающем пространстве имен класса и сделает его видимым только для разрешения перегрузки операторов (не может быть вызвано вручную с помощью синтаксиса :: operator << ...): </p>
class Logger
{
public:
Logger();
~Logger();
std::ostream* out_stream;
template <typename T>
friend Logger& operator<< (Logger& logger, T thing) {
*logger.out_stream << thing;
return logger;
}
/* special treatment for std::wstring. just overload the operator! No need
* to specialize it. */
friend Logger& operator<< (Logger& logger, const std::wstring & wstr) {
/* do something here */
}
};
В качестве альтернативы, чтобы сохранить свой код как есть и просто сделать оператор << шаблон другом, вы добавляете эту строку в определение класса: </p>
template <typename T>
friend Logger& operator<< (Logger& logger, T thing);
Что касается задачи с манипулятором, я просто дам вам свой код, который я написал некоторое время назад:
#include <iostream>
#include <cstdlib>
using namespace std;
template<typename Char, typename Traits = char_traits<Char> >
struct logger{
typedef std::basic_ostream<Char, Traits> ostream_type;
typedef ostream_type& (*manip_type)(ostream_type&);
logger(ostream_type& os):os(os){}
logger &operator<<(manip_type pfn) {
if(pfn == static_cast<manip_type>(std::endl)) {
time_t t = time(0);
os << " --- " << ctime(&t) << pfn;
} else
os << pfn;
return *this;
}
template<typename T>
logger &operator<<(T const& t) {
os << t;
return *this;
}
private:
ostream_type & os;
};
namespace { logger<char> clogged(cout); }
int main() { clogged << "something with log functionality" << std::endl; }
};
Обратите внимание, что это std :: hex, но не std :: ios :: hex . Последний используется в качестве флага-манипулятора для функции setf
потоков. Обратите внимание, что для вашего примера, специальная обработка манипуляторов не требуется. Вышеуказанная специальная обработка std :: endl необходима только потому, что я добавляю потоковое время, когда используется std :: endl.