Почему initializer_list значений enum не считается константным выражением?

Вы хотите on, а не where в последнем операторе sql. С помощью where он выполняет соединение, а затем применяет предложение where, тогда как с on он выполняет соединение относительно условия on.

> sqldf('select matr.*, one.* from matr left outer join one on one.c1 = matr.c1')
  c1 c2   c1   c2
1  a  1    a    1
2  a  1    a    1
3  a  0    a    1
4  b  1    b    1
5  b  1    b    1
6  b  0    b    1
7  b  1    b    1
8  c  0 <NA> <NA>
9  c  0 <NA> <NA>
13
задан Miral 17 January 2019 в 22:54
поделиться

2 ответа

Похоже, что std::initializer_list еще не (в C ++ 17) удовлетворяет требованиям литерального типа (что является требованием типа переменной constexpr ]. удовлетворить).

Обсуждение того, делает ли он это в C ++ 14, можно найти в этом посте: Почему std::initializer_list не определяется как литеральный тип? , который сам был продолжением после обсуждения Законно ли объявлять объект constexpr initializer_list?

Я сравнил цитаты, приведенные в посте, связанном с C ++ 14 (стандарта C ++ 14), с финальным рабочий проект (стандарта C ++ 17) и они одинаковы. Поэтому нет явного требования, чтобы std::initializer_list был литеральным типом.

Цитаты из окончательного рабочего проекта C ++ 17 (n4659):

[basic.types] /10.5

(10.5) a возможно, cv-квалифицированный тип класса (раздел 12), который имеет все следующие свойства:
(10.5.1) - у него есть тривиальный деструктор,
(10.5.2) - это либо тип замыкания (8.1.5.1), агрегатный тип (11.6.1), либо имеющий хотя бы один конструктор constexpr или шаблон конструктора (возможно, унаследованный (10.3.3) от базового класса), который не является конструктором копирования или перемещения ,
(10.5.3) - если это объединение, то по крайней мере один из его нестатических элементов данных имеет энергонезависимый литеральный тип, а
(10.5.4) - если это не объединение, все его нестатические члены-данные и базовые классы относятся к энергонезависимым литеральным типам .

[initializer_list.syn] / 1

  1. Объект типа initializer_list обеспечивает доступ к массиву объектов типа const E. [ Примечание: Пара указателей или указатель плюс длина были бы очевидными представлениями для initializer_list. initializer_list используется для реализации списков инициализаторов, как указано в 11.6.4. Копирование списка инициализатора не копирует базовые элементы. —Конец примечания]

По этой причине нельзя объявить объект constexpr initializer_list.

0
ответ дан P.W 17 January 2019 в 22:54
поделиться

Когда вы инициализируете std::initializer_list, это происходит так:

[dcl.init.list] (выделено мной)

5 Объект типа std :: initializer_list создается из списка инициализаторов , как если бы реализация генерировала и материализовала значение типа «массив N const E» , где N - число элементов в списке инициализатора. Каждый элемент этого массива инициализируется с помощью соответствующего элемента списка инициализатора, и объект std :: initializer_list создается для ссылки на этот массив. [ Примечание : конструктор или функция преобразования, выбранные для копии, должны быть доступны в контексте списка инициализатора. - конец примечания ] Если для инициализации какого-либо из элементов требуется сужающее преобразование, программа некорректна. [ Пример :

struct X {
  X(std::initializer_list<double> v);
};
X x{ 1,2,3 };

Инициализация будет реализована способом, примерно эквивалентным этому:

const double __a[3] = {double{1}, double{2}, double{3}};
X x(std::initializer_list<double>(__a, __a+3));

при условии, что реализация может создать объект initializer_list с пара указателей. - end example ]

То, как этот временный массив используется для инициализации std::initializer_list, определяет, будет ли initializer_list инициализирован константным выражением. В конечном счете, в соответствии с примером (несмотря на то, что он ненормативный), эта инициализация будет принимать адрес массива или его первого элемента, который будет производить значение типа указателя. И это недопустимое константное выражение.

[expr.const] (выделение минное)

5 Постоянное выражение является либо основным константным выражением glvalue это относится к объекту, который является разрешенным результатом постоянного выражения (как определено ниже) или основного постоянного константного выражения, значение которого удовлетворяет следующим ограничениям:

  • , если значение является объектом класса тип, каждый нестатический член данных ссылочного типа относится к объекту, который является разрешенным результатом константного выражения,
  • , если значение имеет тип указателя, оно содержит адрес объекта с статическая длительность хранения, адрес после конца такого объекта ([expr.add]), адрес функции или значение нулевого указателя и
  • , если значение является объектом класс или тип массива, каждый подобъект удовлетворяет этим ограничениям для значения.

Объект является разрешенным результатом константного выражения, если он является объектом со статической продолжительностью хранения, который не является временным объектом или является временным объектом, значение которого удовлетворяет вышеуказанным ограничениям, или является функцией.

Если бы массив был статическим объектом, тогда этот инициализатор представлял бы собой допустимое константное выражение, которое можно использовать для инициализации объекта constexpr. Так как std::initializer_list влияет на время жизни на это временное действие с помощью [dcl.init.list] / 6 , когда вы объявляете group1 как статический объект , clang и gcc Кажется, массив также выделяется как статический объект, что делает правильную инициализацию подчиненной только тому, является ли std::initializer_list литеральным типом, а используемый конструктор - constexpr.

В конечном счете, все это немного мутно.

0
ответ дан StoryTeller 17 January 2019 в 22:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: