So this grew out of Keith Thompson's answer... As far as I know, you can't restrict string literals to only normal functions, but you can do it to macro functions (through a trick).
#include <iostream>
#define LOG(arg) Log(L"" arg)
void Log(const wchar_t *message) {
std::wcout << "Log: " << message << "
";
}
int main() {
const wchar_t *s = L"Not this message";
LOG(L"hello world"); // works
LOG(s); // terrible looking compiler error
}
Basically, a compiler will convert "abc" "def"
to look exactly like "abcdef"
. And likewise, it will convert "" "abc"
to "abc"
. You can use this to your benefit in this case.
I also saw this comment on the C++ Lounge, and that gave me another idea of how to do this, which gives a cleaner error message:
#define LOG(arg) do { static_assert(true, arg); Log(arg); } while (false)
Here, we use the fact that static_assert requires a string literal as it's second argument. The error that we get if we pass a variable instead is quite nice as well:
foo.cc:12:9: error: expected string literal
LOG(s);
^
foo.cc:3:43: note: expanded from macro 'LOG'
#define LOG(arg) do { static_assert(true, arg); Log(arg); } while (false)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…