Почему эти два куска кода с использованием constexpr, __PRETTY_FUNCTION__ и char * имеют разные результаты? - PullRequest
0 голосов
/ 24 сентября 2018

У меня есть этот код, где, если вы закомментируете строку с комментарием " Но это не работает?! ", он компилируется просто отлично, но если нет, компилятор выдаст ошибку.1003 *

По крайней мере, 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();
}

Я столкнулся с этим, пытаясь придумать способ создания тегов профиля для навязчивой системы профилирования во время компиляции .Мне это удалось, но мой окончательный код не включает использование ce_strlen.

1 Ответ

0 голосов
/ 24 сентября 2018

Действительно, это ошибка в 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;
}

Если бы это действительно была переменная, мы ожидали бы, что она пройдет те же тесты, что и эти:

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;
...