constexpr 表达式和模板参数中的文字类型
literal type in constexpr expression and template parameter
为什么我可以在 constexpr 函数中使用非 constexpr 文字类型(例如反射)并且它可以作为 constexpr 返回,但我不能在模板非类型参数中使用此类类型?
class Point {
public:
constexpr Point(double xVal = 0, double yVal = 0) noexcept
: x(xVal), y(yVal)
{}
constexpr double xValue() const noexcept { return x; }
constexpr double yValue() const noexcept { return y; }
constexpr void setX(double newX) noexcept { x = newX; }
constexpr void setY(double newY) noexcept { y = newY; }
private:
double x, y;
};
template <long long N>
void F()
{
std::cout << N << std::endl;
}
constexpr Point reflection(const Point& p) noexcept
{
Point result;
result.setX(p.xValue());
result.setY(p.yValue());
return result; // returning literal non consexpr type
}
int main()
{
constexpr Point p;
F<static_cast<long long>(reflection(p).xValue())>(); //result returned from reflection can be used here
Point p1;
p1.setX(123);
F<static_cast<long long>(p1.xValue())>(); //error: the value of ‘p1’ is not usable in a constant expression
}
constexpr
不是类型的 属性。它是 variable/function 声明中的说明符。
生命周期从常量表达式求值开始的对象可用于该常量表达式,不需要声明 constexpr
。
这里需要是常量表达式的表达式是第一种情况
static_cast<long long>(reflection(p).xValue())
reflection
中的变量 result
仅在该表达式的求值期间存在,并且 p
被声明为 constexpr
。因此两者都可用于常量表达式。
在第二种情况下表达式
static_cast<long long>(p1.xValue())
必须是常量表达式。这使用 p1
,但 p1
未声明 [=12=] 并且其生命周期在表达式求值之前开始,因此它在常量表达式中不可用。更准确地说,xValue()
中要求的 lvalue-to-rvalue 转换违反了常量表达式的要求。
为什么我可以在 constexpr 函数中使用非 constexpr 文字类型(例如反射)并且它可以作为 constexpr 返回,但我不能在模板非类型参数中使用此类类型?
class Point {
public:
constexpr Point(double xVal = 0, double yVal = 0) noexcept
: x(xVal), y(yVal)
{}
constexpr double xValue() const noexcept { return x; }
constexpr double yValue() const noexcept { return y; }
constexpr void setX(double newX) noexcept { x = newX; }
constexpr void setY(double newY) noexcept { y = newY; }
private:
double x, y;
};
template <long long N>
void F()
{
std::cout << N << std::endl;
}
constexpr Point reflection(const Point& p) noexcept
{
Point result;
result.setX(p.xValue());
result.setY(p.yValue());
return result; // returning literal non consexpr type
}
int main()
{
constexpr Point p;
F<static_cast<long long>(reflection(p).xValue())>(); //result returned from reflection can be used here
Point p1;
p1.setX(123);
F<static_cast<long long>(p1.xValue())>(); //error: the value of ‘p1’ is not usable in a constant expression
}
constexpr
不是类型的 属性。它是 variable/function 声明中的说明符。
生命周期从常量表达式求值开始的对象可用于该常量表达式,不需要声明 constexpr
。
这里需要是常量表达式的表达式是第一种情况
static_cast<long long>(reflection(p).xValue())
reflection
中的变量 result
仅在该表达式的求值期间存在,并且 p
被声明为 constexpr
。因此两者都可用于常量表达式。
在第二种情况下表达式
static_cast<long long>(p1.xValue())
必须是常量表达式。这使用 p1
,但 p1
未声明 [=12=] 并且其生命周期在表达式求值之前开始,因此它在常量表达式中不可用。更准确地说,xValue()
中要求的 lvalue-to-rvalue 转换违反了常量表达式的要求。