I need to interface with an API that expects compile time static strings. It enforces them via using
static_assert (__builtin_constant_p (str));
To be more specific, I'm referring to the Apple Signpost API here.
Now I have a situation where I'd like to pass a constexpr string to this interface, which however fails due to a compiler error. It boils down to this simple test case
constexpr std::string_view s = "foo";
static_assert (__builtin_constant_p (s));
which fails at the static_assert with Apple Clang 14. Now I wonder why this is the case? In their documentation on builtins, clang refers to GCC documentation, which states
You can use the built-in function __builtin_constant_p to determine if a value is known to be constant at compile time [...]
To my understanding a constexpr value is known to be constant at compile time. Why does this assertion still fail then?
As pointed out in the comments it seems that even GCC and clang behave different here so the conclusion is that the definition of the compiler builtin is way to loose in order to expect it to align with the definition of a C++ constant expression.
Still, I found a solution for my specific problem. Previously, I was trying to pass a constexpr string literal to the
os_signpost_interval_beginmacro likeThis triggered a static assertion hidden deeper in the that macro since
__builtin_constant_p (s.data())evaluated to false, which then led me to create that test case presented in the original question.In the meantime, I let my IDE inline the invocation of the
os_signpost_interval_beginmacro, which revealed some more context of that assertion. We find a macro like this being usedso as far as I get it, that string literal variable is placed into a specific section of the binary where the profiler will expect it. Creating that variable this way by passing a
const char*pointer as string to that macro rather than a literal would indeed not yield to code that compiles, so it seems that the assertion here makes some sense for this very particular use case.As a workaround, I replicated the content of the macro myself inside a function template that takes a
std::index_sequenceof the string length and generate an assignment from a compile time static string by unpacking it character by character into an initializer list through an index sequence likewhich proved to solve my problem.