Ответ 1
Все, что обращается к this
вне контекста constexpr
, не является not константным выражением, как определено в [expr.const]/2.1:
Выражение e является основным константным выражением , если при вычислении e, следуя правилам абстрактной машины, не будет выполнено одно из следующих выражений:
this
, за исключением функцииconstexpr
или конструктораconstexpr
, который оценивается как часть e;
(Нам нужен this
для доступа к n
, чтобы передать его в getArgCount
по ссылке)
Так вот почему первый случай не компилируется.
Второй случай компилируется, потому что он не включает преобразование lvalue-в-значение непостоянной величины (sizeof(n)
на самом деле не "читает" n
).
Чтобы продемонстрировать это, также будет скомпилировано следующее:
struct A
{
int n;
void f()
{
int m = n;
static_assert(getArgCount(m) > 0); // ok, m does not need 'this'
}
};
Примечание. Наличие ссылки внутри контекста constexpr
(части Types&&
) само по себе не нарушает "constexpr-ness", если время жизни ссылки началось в этом контексте: [expr.const]/2.11.2.
Другой пример:
struct A
{
int n;
void f()
{
static_assert(sizeof(n) > 0); // ok, don't need this for sizeof(A::n)
}
};
Следующее не будет компилироваться:
int n = 1;
static_assert(getArgCount(n+1) > 0); // not ok, (n+1) "reads" n