I’m writing a logging class that uses a templatized operator<< function. I’m specializing the template function on wide-character string so that I can do some wide-to-narrow translation before writing the log message. I can’t get TCHAR to work properly – it doesn’t use the specialization. Ideas?
Here’s the pertinent code:
// Log.h header
class Log
{
public:
template <typename T> Log& operator<<( const T& x );
template <typename T> Log& operator<<( const T* x );
template <typename T> Log& operator<<( const T*& x );
...
}
template <typename T> Log& Log::operator<<( const T& input )
{ printf("ref"); }
template <typename T> Log& Log::operator<<( const T* input )
{ printf("ptr"); }
template <> Log& Log::operator<<( const std::wstring& input );
template <> Log& Log::operator<<( const wchar_t* input );
And the source file
// Log.cpp
template <> Log& Log::operator<<( const std::wstring& input )
{ printf("wstring ref"); }
template <> Log& Log::operator<<( const wchar_t* input )
{ printf("wchar_t ptr"); }
template <> Log& Log::operator<<( const TCHAR*& input )
{ printf("tchar ptr ref"); }
Now, I use the following test program to exercise these functions
// main.cpp - test program
int main()
{
Log log;
log << "test 1";
log << L"test 2";
std::string test3( "test3" );
log << test3;
std::wstring test4( L"test4" );
log << test4;
TCHAR* test5 = L"test5";
log << test5;
}
Running the above tests reveals the following:
// Test results
ptr
wchar_t ptr
ref
wstring ref
ref
Unfortunately, that’s not quite right. I’d really like the last one to be “TCHAR”, so that I can convert it. According to Visual Studio’s debugger, the when I step in to the function being called in test 5, the type is wchar_t*& – but it’s not calling the appropriate specialization. Ideas?
I’m not sure if it’s pertinent or not, but this is on a Windows CE 5.0 device.
A-HA!
So, I broke the problem down into it’s smallest part and discovered something about the order in which template functions are matched. First, I broke the program down into this:
And
// Log.h
And
// Log.ccp
And sure enough, my template specialization got called. When I added another specialization to the Log header like this
The compiler started matching the new function instead. This time, however, I didn’t include a definition for the template, so the linker complained. The linker showed the following error:
This told me the type it was trying to match:
A const pointer, not a pointer-to-const reference! So, now my program works. I just specialize the template like so:
Thanks for the help everyone.