为什么使用constexpr,__ PRETTY_FUNCTION__和char*的这两段代码有不同的结果?

Omn*_*ous 17 c++ gcc constexpr c++17

我有这个代码,如果你注释掉行注释" 但这不起作用?! "它编译得很好,但如果你没有,编译器会产生错误.

至少,gcc 8.2会产生错误.

但是,它们似乎与我相同.有什么问题?这是合法代码吗?

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();
}
Run Code Online (Sandbox Code Playgroud)

我试图想出一种在编译时为侵入性分析系统创建配置文件标签的方法.我成功了,但我的最终代码不涉及使用ce_strlen.

小智 15

事实上,这是GCC中的错误,正如评论中所讨论的那样,但我认为我会对这个错误的性质提出一些额外的见解.在GCC NEWS文件中有这一行:

  • __FUNCTION__并且__PRETTY_FUNCTION__现在被解析器视为变量; 以前他们被视为字符串常量.因此printf (__FUNCTION__ ": foo")必须重写代码printf ("%s: foo", __FUNCTION__).这对模板来说是必要的.

__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;
}
Run Code Online (Sandbox Code Playgroud)

如果它确实是一个变量,我们希望它通过相同的测试用例:

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;
Run Code Online (Sandbox Code Playgroud)