const работает, но не constexpr - PullRequest
       30

const работает, но не constexpr

2 голосов
/ 27 февраля 2020

Это вопрос о моей голове, но он работает, с const, но не с constexpr, и мне интересно, можете ли вы, умные люди, объяснить. Скомпилировано с g ++ -std = c ++ 14.

struct Service
{
    std::string name;
    enum {
        thread,
        interrupt,
        end_types
    } que_type;
};

const Service namedServices[] =
{
    {"abc", Service::thread},
    {"efg", Service::thread},
    {"hij", Service::interrupt},
    {"klm", Service::thread},
    {"nop", Service::interrupt},
    {"qrs", Service::thread},
    {"", Service::end_types}
};

constexpr int thcnt()
{
    int cnt = 0;
    for (const Service* sp = namedServices; sp->que_type != Service::end_types; sp++) {
        if (sp->que_type == Service::thread)
            cnt++;
    }
    return cnt;
}
int main(int argc, char** argv)
{
    std::string strs[thcnt()];
 ...

Это компилируется и, насколько я могу судить, делает правильные вещи. Если я перехожу на

constexpr Service namedServices[] =

, я получаю

... error: the type 'const Service []' of constexpr variable 'namedServices' is not literal
 };
 ^

Это кажется странным, но, возможно, на это есть веская причина. Или, может быть, это будет исправлено в c ++ 20.

спасибо

1 Ответ

6 голосов
/ 27 февраля 2020

namedServices не является LiteralType , поскольку это массив класса, содержащий std::string, который не является LiteralType. Следовательно, это не может быть constexpr.

. Обратите внимание, что ваша функция thcnt() фактически вызывает неопределенное поведение без необходимости диагностики c, потому что в ней нет случаев постоянной оценки, поскольку namedServices не имеет постоянной оценки ; и std::string strs[thcnt()]; проходит, только если у вас включены VLA, которые g ++ делает по умолчанию. Используйте -pedantic для получения соответствия ISO.

Начиная с C ++ 20 будет consteval спецификатор , чтобы вызвать ошибку компиляции вместо UB NDR, это поддерживается clang trunk (пример) .


Я видел некоторые предположения, что C ++ 20 будет иметь constexpr std::string, однако clang trunk (по крайней мере, версия Godbolt) не поддерживает это, и C ++ 20 еще не совсем завершен. Может случиться так, что ваш код станет легальным в C ++ 20.

Тем временем вы можете сделать код легальным, используя constexpr Service namedServices[] и:

  • В C ++ 14 или позже, используя const char *name;
  • В C ++ 17, используя std::string_view name;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...