I have this code which returns modified function name string provided by __PRETTY_FUNCTION__
macro at compile time:
template<size_t N>
struct SL
{
char value[N];
constexpr SL(const char (&str)[N])
{
for(size_t i = 0; i != N; ++i)
value[i] = str[i];
}
};
template<SL literal>
consteval auto PrettifyFunctionName()
{
...
}
I use it like this:
constexpr auto resultName = PrettifyFunctionName<__PRETTY_FUNCTION__>();
I'd like to replace the macro __PRETTY_FUNCTION__
with std::source_location::function_name()
How can I pass it as the template argument?
Is there another way to get it as constexpr
value in PrettifyFunctionName?
Add a constructor to SL
that copies from a const char*
into the array exactly as your current loop does and then:
constexpr auto funcName = std::source_location::current().function_name();
constexpr auto resultName = PrettifyFunctionName<SL<mystrlen(funcName)+1>(funcName)>();
You will need to define mystrlen
equivalently to strlen
yourself, because std::strlen
is not marked constexpr
.
It is not possible to avoid naming funcName
twice, because its type doesn't contain information about its length and it isn't specified whether or not the result of function_name
refers to a string literal. If it refers to a string literal, then it can't be passed directly as a template argument.
You could however replace mystrlen(funcName)+1
with some sufficiently large number. It will then fail to compile if the actual function name is too long.
It may be easier to pass the string as function argument instead of template argument, assuming you don't need the string to be part of the type of resultName
later on.
I think compile-time use of source_location
isn't specified well btw.
The member functions are marked constexpr
indicating that they should be usable at compile-time, but the result of function_name
is only specified to refer to some null-terminated byte string.
It doesn't say whether that string is supposed to have static storage duration so that the pointer can be stored in a constexpr
variable, whether it may refer to a string literal, so that it can't be used as template argument directly, and whether its elements are usable in constant expressions, so that the actual contents of the string can be inspected in constant expressions. (Although the first one kind of follows from current
being marked consteval
.)
But it is a general issue that library functions marked constexpr
lack precise specification of which compile-time use is guaranteed and which is not.