Является ли тип указателя буквенным типом?

code707 спросил: 28 апреля 2018 в 09:40 в: c++

Скалярный тип определяется как

Класс признака, который определяет, является ли T скалярным типом. Скалярный тип - это тип, который имеет встроенную функциональность для оператора сложения без перегрузок (арифметика, указатель, указатель-член, enum иstd :: nullptr_t).

Он наследует от integ_constant как true_type orfalse_type, в зависимости от то ли T является скалярным типом, независимо от его константы и / или волютивной квалификации.

Это означает, что указатель является скалярным типом.

Теперь, если мы перейдем к определению типа литерала :

Тип - это тип литерала, если он:

  • скалярный тип; или
  • ссылочный тип; или
  • массив типа literal; или-тип класса (раздел 9), который имеет все следующие свойства:
    • он имеет тривиальный деструктор,
    • каждый вызов конструктора и полное выражение в скобках или равных -инициализаторы для нестатических членов данных (если они есть) являются постоянным выражением (5.19),
    • это агрегированный тип (8.5.1) или имеет хотя бы один конструктор конструктора или конструктора constexpr, который не является конструктор копирования или перемещения и
    • все его нестатические элементы данных и базовые классы имеют литеральные типы.

Теперь, комбинируя выше 2-х операторов, это означает, что указатель является литералом типа. Однако указатель не может быть constexpr. кто-то может прояснить?

далее см. следующий код:

int a = 7;
constexpr int *pointer1 = &a;
int main ()
{
  int b = 4;
  constexpr int *pointer2 = &b;
}

pointer1 отлично, но указатель 2 дает ошибку. означает ли это указатель на глобальный, но автоматическая переменная не так ли? Описывает ли стандарт в любом месте?

2 ответа

Есть решение
HolyBlackCat ответил: 28 апреля 2018 в 03:07

Указатели являются буквальными. Они могут быть constexpr при определенных условиях:

[expr.const] 6

... [указатель constexpr if] содержит адрес объекта со статической продолжительностью хранения, адрес после конца такого объекта (5.7), адрес функции или значение нулевого указателя.

(Где "со статической продолжительностью хранения означает глобальный или статический объект или подобъект такого объекта.)

Демо:

int x;int main()
{
    constexpr int *ptr = &x; // Compiles.    // Doesn't compile: `error: '& foo' is not a constant expression`
    // int foo;
    // constexpr int *bar = &foo;
}

Очевидно, что GCC (с кодом -pedantic-errors -std=c++11 / 14 / 17) с радостью принимает внеуровневую арифметику указателя constexpr: constexpr int *ptr = &x - 10;, который кажется мне ошибкой.

hvd ответил: 28 апреля 2018 в 09:47
Я понимаю, что вы имеете в виду, но это не совсем правильно. В int x; constexpr int *p = &x + 1;, p не является нулевым и не указывает на глобальный или статический объект.
HolyBlackCat ответил: 28 апреля 2018 в 09:49
@hvd Точка взята. Теперь лучше?
hvd ответил: 28 апреля 2018 в 09:52
Да, это лучше, с регулярным предупреждением о том, что неопределенное поведение делает выражение непостоянным, поэтому int x; constexpr int *p = &x + 2; не подходит. Для полноты они также могут указывать на функции, когда вы имеете дело с типами указателей.
Swift - Friday Pie ответил: 28 апреля 2018 в 10:19
возможно, "адрес, находящийся за концом такого объекта", применяется к обоим концам. во всяком случае, это, скорее всего, цитата из проекта, которая является "неполной и интрект",
HolyBlackCat ответил: 28 апреля 2018 в 03:00
@ Swift-FridayPie Я предполагаю, что "адрес за концом такого объекта" означает"ровно один байт за фактический конец (не начало)". И цитата была там, по крайней мере, с C ++ 14 и не сильно изменилась ...
Yakk - Adam Nevraumont ответил: 28 апреля 2018 в 09:45

Да, это литералы; да, они могут быть constexpr. Чтобы продемонстрировать:

constexpr int* foo=0;int x = 7;constexpr int* ptr=&x;int main(){}