misturando o uso de constexpr e const?

Eu li um pouco da implementação CLang da biblioteca padrão e isso me confunde um pouco em const e constexpr.

template<class _Tp, _Tp __v>
struct integral_constant
{
    static constexpr _Tp value = __v;
};

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

O que me deixa confuso é que ele está usando constexpr dentro da definição de classe e const fora. Minha pergunta é: isso é permitido? E sob que situação const e constexpr podem ser usados de forma intercambiável? É claro que as funções constexpr não podem se aplicar a const, então estou falando de dados const e dados constexpr.

Eu li alguns rascunhos padrão e a proposta emhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf, mas me sinto mais confuso. Então, eu tenho mais algumas perguntas,

Na N2235, afirma claramente que, os dados const não são garantidos como constantes de tempo de compilação, consulte o exemplo a seguir,

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

e constexpr deve resolver isso; portanto, pelo menos nessa situação, constexpr não é permitido como abaixo,

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

No entanto, depois de ler o rascunho do padrão C ++ N3225, não vejo nenhum lugar explícito que o exemplo acima cause um erro. Particularmente, de 7.1.5 / 9,

Um especificador constexpr usado em uma declaração de objeto declara o objeto como const. Esse objeto deve ter um tipo literal e deve ser inicializado. Se for inicializado por uma chamada de construtor, o construtor deve ser um construtor constexpr e todo argumento para o construtor deve ser uma expressão constante. essa chamada deve ser uma expressão constante (5.19). Caso contrário, toda expressão completa que aparecer em seu inicializador deve ser uma expressão constante.

Portanto, se constexpr int limit = 2 * S :: size; é inválido, então S :: size não deve ser uma expressão constante; em seguida, a partir de 5.19 (expressão constante), não vejo em nenhum lugar o padrão 2 * S :: size desaprovar no exemplo acima para não ser uma expressão constante.

Alguém pode apontar algo que eu negligenciei? Muito obrigado.

questionAnswers(2)

yourAnswerToTheQuestion