为什么这两段使用constexpr、__PRETTY_FUNCTION__和char *的代码会有不同的结果呢?

Why do these two pieces of code using constexpr, __PRETTY_FUNCTION__ and char * have different results?

我有这段代码,如果您注释掉注释为“But this doesn't work?!”的行,它编译得很好,但如果不这样做,编译器生成错误。

至少,gcc 8.2 generates an error.

但是,他们看起来和我一样。有什么问题?这是合法的代码吗?

template <int x>
struct test_template {
    static int size() { return x; }
};

constexpr int ce_strlen(char const *s)
{
    int i = 0;
    while (s[i]) ++i;
    return i;
}

int joe()
{
    constexpr int plen = ce_strlen(__PRETTY_FUNCTION__); // This works
    test_template<plen> a; // This declaration is valid.
    test_template<ce_strlen(__PRETTY_FUNCTION__)> b; // But this doesn't work?!
    return a.size() + b.size();
}

我 运行 在试图想出 a way to create profile tags for an intrusive profiling system at compile time 的时候参与其中。我成功了,但我的最终代码不涉及使用 ce_strlen.

确实,正如评论中所讨论的那样,这是 GCC 中的一个错误,但我想我会就此错误的性质提出一些额外的见解。在 GCC NEWS file 中有这一行:

  • __FUNCTION__ and __PRETTY_FUNCTION__ are now treated as variables by the parser; previously they were treated as string constants. So code like printf (__FUNCTION__ ": foo") must be rewritten to printf ("%s: foo", __FUNCTION__). This is necessary for templates.

但是 __PRETTY_FUNCTION__ 并不是一个真正的变量,它是在解析器中处理的一种特殊情况,正如我们在 constexpr.c:

中看到的
    case DECL_EXPR:
      {
    tree decl = DECL_EXPR_DECL (body);
    if (TREE_CODE (decl) == USING_DECL
        /* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__.  */
        || DECL_ARTIFICIAL (decl))
      return NULL_TREE;
    return error_mark_node;
}

如果它真的是一个变量,我们希望它能通过与这些相同的测试用例:

constexpr const char* s2 = "TEST";
constexpr const char* s3 = s2;
test_template<ce_strlen("TEST")> c;
test_template<ce_strlen(s2)> d;
test_template<ce_strlen(s3)> e;