Это ошибка?Конструктор Constexpr молча становится не constexpr - PullRequest
0 голосов
/ 05 декабря 2018

Посмотрите на этот код:

struct NonConstexpr {
    NonConstexpr() { }
};

template <typename T>
struct Bar {
    NonConstexpr nonConstexpr;

    constexpr Bar() { }
};

struct Foo {
    Bar<void> bar;

    constexpr Foo() { }
};

Foo имеет член Foo::bar::nonConstexpr, который имеет конструктор non-constexpr.Итак, я ожидаю, что это не должно компилироваться.Но он компилируется с gcc, clang и msvc.Это ошибка компилятора или какое-то правило позволяет компилировать этот код?

Если я добавлю NonConstexpr член в Foo напрямую, код больше не будет компилироваться.

(У меня возникла эта проблема, потому что я ожидал статическую инициализацию для глобального Foo объекта, но он был динамически инициализирован, и это вызвало проблему из-за «статического порядка инициализации фиаско»)

1 Ответ

0 голосов
/ 05 декабря 2018

Это ошибка компилятора, или какое-то правило позволяет этот код компилировать?

Правило, которое позволяет это компилировать:

10.1.5 Спецификатор constexpr [dcl.constexpr]
...
6. Если конкретизированная шаблонная специализация шаблона функции constexpr или функции-члена шаблона класса не сможет удовлетворитьТребования к constexpr функции или constexpr конструктору, эта специализация по-прежнему является constexpr функцией или constexpr конструктором, даже если вызов такой функции не может появляться в константном выражении.Если никакая специализация шаблона не удовлетворяет требованиям для функции constexpr или конструктора constexpr, если она рассматривается как не шаблонная функция или конструктор, шаблон не сформирован, диагностика не требуется.

Приведенная выше цитата взята из стандартного проекта CPP N4713.


Из цитаты может быть неясно, как конструктор Bar<void> может отображаться в Fooконструктор Foo конструктор constexpr.Но, как отмечено в комментариях, constexpr - это не то же самое, что постоянное выражение.Конструктор Foo не является выражением, а тем более константным выражением.

...