I read a little of CLang implementation of standard library and it confuses me a little bit on const and 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;
What makes me confusing is that, it is using constexpr inside class definition and const outside. My question is, is that allowed? And under what situation const and constexpr can be used interchangeably? Of course constexpr functions cannot apply to const, so I am talking about const data and constexpr data.
I did read some standard draft and the proposal in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf, but it makes me feel more confusing. So I have some more questions,
In N2235, it clearly states that, const data are not guaranteed to be a compile time constants, see the following example,
struct S {
static const int size;
};
const int limit = 2 * S::size; // dynamic initialization
const int S::size = 256;
and constexpr is supposed to solve this, so at least under this situation, constexpr is not allowed as below,
struct S {
static const int size;
};
constexpr int limit = 2 * S::size; // shall be error in my understanding
const int S::size = 256;
However, after reading C++ standard draft N3225, I see nowhere explicitly stated that the above example shall cause an error. Particularly, from 7.1.5/9,
A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, the constructor shall be a constexpr constructor and every argument to the constructor shall be a constant expression. that call shall be a constant expression (5.19). Otherwise, every full-expression that appears in its initializer shall be a constant expression.
Therefore, if constexpr int limit = 2 * S::size; is invalid, then S::size must not be an constant expression, then from 5.19 (constant expression), I see nowhere the standard disallow 2 * S::size in the above example to not be a constant expression.
Can anybody point out anything I have overlooked? Thank you very much.