I believe the answer to your question is no -- but here's a way to do something similar.
Define a macro, and use the #
"stringification" operator to guarantee that only a string literal will be passed to the function (unless somebody bypasses the macro and calls the function directly). For example:
#include <iostream>
#define LOG(arg) Log(#arg)
void Log(const char *message) {
std::cout << "Log: " << message << "\n";
}
int main() {
const char *s = "Not this message";
LOG("hello world");
LOG(hello world);
LOG(s);
}
The output is:
Log: "hello world"
Log: hello world
Log: s
The attempt to pass s
to LOG()
did not trigger a compile-time diagnostic, but it didn't pass that pointer to the Log
function.
There are at least two disadvantages to this approach.
One is that it's easily bypassed; you may be able to avoid that by searching the source code for references to the actual function name.
The other is that stringifying a string literal doesn't just give you the same string literal; the stringified version of "hello, world"
is "\"hello, world\""
. I suppose your Log
function could strip out any "
characters in the passed string. You may also want to handle backslash escapes; for example, "\n"
(a 1-character string containing a newline) is stringified as "\\n"
(a 2-character string containing a backslash and the letter n
).
But I think a better approach is not to rely on the compiler to diagnose calls with arguments other than string literals. Just use some other tool to scan the source code for calls to your Log
function and report any calls where the first argument isn't a string literal. If you can enforce a particular layout for the calls (for example, the tokens Log
, (
, and a string literal on the same line), that shouldn't be too difficult.