Description
[dcl.constexpr] p6 says
For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression, or, for a constructor, an evaluated subexpression of the initialization full-expression of some constant-initialized object ([basic.start.static]), the program is ill-formed, no diagnostic required.
The condition here requires an argument to make the rule true. Consider this example:
constexpr int fun(){
const int v = 0;
if(v==1){
static int v = 0;
}
return v;
}
struct A{
constexpr int show(){
if(a==1){
static int v = 0;
}
return a;
}
int a = 0;
};
No argument here, however, the example is accepted by implementations. I think the argument is not necessary here to make the rule true. Maybe, we just need to say
For a constexpr function or constexpr constructor that is neither defaulted nor a template, if there does not exist an invocation of the function or constructor such that the function call could be an evaluated subexpression of a core constant expression, or, for a constructor, an evaluated subexpression of the initialization full-expression of some constant-initialized object ([basic.start.static]), the program is ill-formed, no diagnostic required.
In the above example, there exists such an invocation(e.g. v!=1, a!=1
). As a contract example:
struct NoneLiteral{
NoneLiteral(){}
~NoneLiteral(){}
};
struct B:NoneLiteral{
int a;
constexpr int fun(){
return a;
}
};
Since B
is not a literal type and cannot be used to create a constexpr
object or temporary object of the type within the context of a core constant expression, thus the lvalue-to-rvalue conversion that is applied to a
can never satisfy the requirement of a core constant expression.