C++ 为什么使用constexpr、PRETTY函数和char*的这两段代码有不同的结果?

C++ 为什么使用constexpr、PRETTY函数和char*的这两段代码有不同的结果?,c++,gcc,c++17,constexpr,C++,Gcc,C++17,Constexpr,我有这样一段代码,如果你注释掉一行注释“但这不起作用?!”它编译得很好,但是如果你不这样做,编译器会生成一个错误 至少 但是,它们在我看来是一样的。有什么问题吗?这是法律法规吗 template <int x> struct test_template { static int size() { return x; } }; constexpr int ce_strlen(char const *s) { int i = 0; while (s[i]) ++

我有这样一段代码,如果你注释掉一行注释“但这不起作用?!”它编译得很好,但是如果你不这样做,编译器会生成一个错误

至少

但是,它们在我看来是一样的。有什么问题吗?这是法律法规吗

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();
}
模板
结构测试模板{
静态int size(){return x;}
};
constexpr int ce_strlen(char const*s)
{
int i=0;
而(s[i])++i;
返回i;
}
int joe()
{
constexpr int plen=ce_strlen(uu PRETTY_FUNCTION_uuu);//这很有效
test_template a;//此声明有效。
test_template b;//但这不起作用?!
返回a.size()+b.size();
}

我在想办法的时候碰到了这个。我成功了,但是我的最终代码没有涉及到使用
ce\u strlen

正如评论中所讨论的,这确实是GCC中的一个bug,但是我想我会对这个bug的性质提出一些额外的见解。GCC中有以下行:

  • 解析器现在将
    \uuuuuuuuuuuuuuuuu函数
    \uuuuuuuu漂亮的函数
    视为变量;以前,它们被视为字符串常量。因此,像
    printf(\uuuu函数\uuuuuuuuuuuuuuuuuuuuuuo”)
    这样的代码必须重写为
    printf(“%s:foo”,\uuuuuuuuu函数)
    。这对于模板是必需的
但是
\uuu PRETTY\u FUNCTION\uuuu
并不是一个真正的变量,它是解析器中处理的一个特例,正如我们在
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;
constexpr const char*s2=“测试”;
constexpr const char*s3=s2;
测试模板c;
测试模板d;
测试模板e;

嗯,
\uu PRETTY\u函数\uuu
不是标准的。(
\uuuu func\uuuu
是,但对于您的目的来说可能不够独特,尤其是在存在重载和模板的情况下。)@aschepler-我相信已经有了一种运动,可以标准化类似于
\uu PRETTY\u FUNCTION\uuuuu
的东西。但是,这就是为什么我在gcc标签中添加了::-)这和叮当似乎没有问题的代码。还有,兰博达斯。lambda在这里是一个非常有趣的例子。鉴于
ce\u strlen
返回一个
int
,它的类型也与
test\u template
的非类型模板参数相同-没有理由它们会有不同的行为。我很难处理[expr.const],但至少我很确定它们要么都编译,要么都失败.field。我最好的猜测是两者都应该失败,但这肯定是一个行为不同的bug。根据,
\uu PRETTY\u FUNCTION\uuu
是constexpr,因此这两种情况都应该编译。感谢您提供有关gcc内部发生了什么导致此问题的有趣细节。:-)