Let\'s say I have these two overloads:
void Log(const wchar_t* message)
{
// Do something
}
void Log(const std::wstring& message)
{
// Do someth
If you define Log as a macro instead, and call separate methods for literal versus std::wstring handling, some variation of the following should work:
#define Log(x) ((0[#x] == 'L' && 1[#x] == '"') ? LogLiteral(x) : LogString(x))
void
LogLiteral (const wchar_t *s) {
//...do something
}
void
LogString (const std::wstring& s) {
//...do something
}
The trick is that you need opposing definitions of LogLiteral() so that the compilation will pass, but it should never be called.
inline void LogLiteral (const std::wstring &s) {
throw std::invalid_argument(__func__);
}
This code gives you the behavior of an overloaded Log() method, in that you can pass either a string literal or a non-string literal to the Log() macro, and it will end up calling either LogLiteral() or LogString(). This gives compile time verification in that the compiler will not pass anything except what the code recognizes as a string literal to the call to LogLiteral(). At sufficient optimizations, the conditional branch can be removed, since every instance of the check is static (on GCC, it is removed).