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

时间:2018-09-24 02:26:10

标签: c++ gcc c++17 constexpr

我有这段代码,如果您在注释为“ 但这行不通?!”的行中注释掉,它可以正常编译,但是如果不这样做,则编译器会生成错误。

至少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

1 个答案:

答案 0 :(得分:15)

实际上,正如评论中所讨论的,这是GCC中的一个错误,但是我认为我对该错误的性质有一些其他的见解。在海湾合作委员会NEWS file中,有以下这一行:

  
      现在,解析器将
  • __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;
}

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

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;