Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__PRETTY_FUNCTION__ in constant expression

Please refer to this snippet:

#include <type_traits>
#include <string_view>

constexpr std::size_t strlen(char const* s) {
    std::size_t n = 0;
    while (*s++ != '\0')
        ++n;
    return n;
}

template <std::size_t>
struct X {};

int main() {
    constexpr auto pf = __PRETTY_FUNCTION__; // gcc ok; clang ok; (1)
    static_assert(std::string_view(__PRETTY_FUNCTION__) == std::string_view("int main()")); // gcc ok; clang ok; (2)
    X<strlen(__PRETTY_FUNCTION__)> x; // gcc not ok; clang ok; (3)
}

Clang 8 compiles it, but GCC 8.3 dos not. See on godbolt. GCC fails on line (3) although lines (1) and (2) are ok. If I am able to declare pf in line (1) and use __PRETTY_FUNCTION__ in static_assert it means that the expression __PRETTY_FUNCTION__ is core constant expression. And if I'm not able do declare X<strlen(__PRETTY_FUNCTION__)> x it means that strlen(__PRETTY_FUNCTION__) is not an integral constant expression.

So why strlen(__PRETTY_FUNCTION__) is not an integral constant expression? Is it implied by the standard, or is it a GCC bug?

like image 448
nicolai Avatar asked Apr 25 '19 13:04

nicolai


People also ask

What is the difference between __function__ and __pretty_function__?

__PRETTY_FUNCTION__ is a gcc extension that is mostly the same as __FUNCTION__, except that for C++ functions it contains the "pretty" name of the function including the signature of the function. Visual C++ has a similar (but not quite identical) extension, __FUNCSIG__.

What is a constant expression in C++?

Constant expression. Literal constant expression is a prvalue core constant expression of non-pointer literal type (after conversions as required by context). A literal constant expression of array or class type requires that each subobject is initialized with a constant expression.

What is a core constant expression?

Constant expression. A constant expression is either. a glvalue core constant expression that refers to. an object with static storage duration that is not a temporary, or. an object with static storage duration that is a temporary, but whose value satisfies the constraints for prvalues below, or.

When is a function needed for constant evaluation?

A function is needed for constant evaluation if it is a constexpr function and named by an expression that is potentially constant evaluated.


1 Answers

__PRETTY_FUNCTION__ is not standard. As such a compiler can implement it in different places (while parsing, while building the AST or while linking).

If it's supposed to be implemented while parsing, then it can be a constant expression (I guess that's what clang is doing). However, if it's implemented while linking (that is, the compiler emits a symbol for it and the linker will resolve it), it can't be a constant expression.

I think GCC use the latter case.

Please notice that you can take a sizeof() of these in that case, since it's a const char[] if you need compile-time constant string's length computation. So replace expression 3 by:

X<sizeof(__PRETTY_FUNCTION__) - 1> x;

and it'll compile fine on both compiler.

EDIT: As NathanOliver pointed out, it seems that GCC consider the signature of __PRETTY_FUNCTION__ as static const char[] while clang/visual studio consider it as static constexpr const char[]. This is a painful nuisance in GCC (not a bug, since it's not standard) and they seems to have fixed it in the >8.0.0 version.

In expression (1) and expression (2), __PRETTY_FUNCTION__ is decayed to a const char* (the pointer are constant, but nothing can be said about the data). For me, expression (2) might not prove anything, since there is no guarantee the pointers should be equal on both side of the equality, even if they points to the "same" content. string_view constructor expects const char*, thus anything other than __PRETTY_FUNCTION__ that could decay to const char* would pass expression (2).

like image 130
xryl669 Avatar answered Sep 20 '22 09:09

xryl669