смешивание использования constexpr и const?

Я немного прочитал о реализации стандартной библиотеки CLang, и меня немного смущает const и constexpr.

template
struct integral_constant
{
    static constexpr _Tp value = __v;
};

template
const _Tp integral_constant<_Tp, __v>::value;

Меня сбивает с толку то, что внутри определения класса используется constexpr и const вне. У меня вопрос, это разрешено? И в какой ситуации const и constexpr могут использоваться как взаимозаменяемые? Конечно, функции constexpr не могут применяться к const, поэтому я говорю о данных const и constexpr.

Я прочитал некоторые стандартные черновики и предложения в http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf , но это сбивает меня с толку. Итак, у меня есть еще несколько вопросов,

В N2235 четко указано, что данные const не гарантированно являются константами времени компиляции, см. Следующий пример,

struct S {
    static const int size;
};
const int limit = 2 * S::size; // dynamic initialization
const int S::size = 256;

, и constexpr должен решить эту проблему, поэтому по крайней мере ниже В этой ситуации constexpr не допускается, как показано ниже,

struct S {
    static const int size;
};
constexpr int limit = 2 * S::size; // shall be error in my understanding
const int S::size = 256;

Однако, после прочтения проекта стандарта C ++ N3225, я нигде не вижу явного указания, что приведенный выше пример вызовет ошибку. В частности, из 7.1.5 / 9

Спецификатор constexpr, используемый в объявление объекта объявляет объект как const. Такой объект должен иметь буквальный тип и должен быть инициализирован. Если он инициализирован конструктором вызов, конструктор должен быть constexpr конструктор и каждый аргумент конструктора должен быть постоянное выражение. этот звонок должен - постоянное выражение (5.19). В противном случае каждое полное выражение, которое появляется в его инициализаторе, должен быть постоянное выражение.

Следовательно, если constexpr int limit = 2 * S :: size; является недопустимым, то S :: size не должно быть постоянным выражением, то начиная с версии 5.19 (постоянное выражение) я нигде не вижу, чтобы стандартный запрет 2 * S :: size в приведенном выше примере не был постоянным выражением.

Может Кто-нибудь указал на то, что я упустил? Большое спасибо.

8
задан badola 9 August 2018 в 14:57
поделиться