Search code examples
c++templatesconstexpr

c++ pass std::source_location::function_name() as string literal template argument


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?


Solution

  • 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.