constexpr 与 const 引用交互的奇怪行为
Strange behavior with constexpr interacting with const references
我用 clang 和 gcc(主干版本)测试了以下代码。有人可以解释为什么使用普通 X 结构的情况不起作用,而按值捕获和使用 const 引用的包装器情况都可以正常工作。
struct X {
constexpr X(const int &v) : x(v) {}
constexpr int Get() const { return x; }
private:
const int& x;
};
constexpr X f(const X& r) {
return r;
}
struct Y {
constexpr Y(const int &v) : x(v) {}
constexpr int Get() const { return x; }
private:
const int x;
};
constexpr Y f(const Y& r) {
return r;
}
struct Wrap {
constexpr Wrap(const int& v) : x(v) {}
constexpr Y Get() const { return Y{x}; }
private:
const int x;
};
int main() {
constexpr const int x = 10;
/* this does not work for some reason
constexpr X a(x);
static_assert(f(a).Get() == 10, "This should work.");
*/
// This works.
constexpr Y b(x);
static_assert(f(b).Get() == 10, "This should work.");
// This also works.
constexpr Wrap c(x);
static_assert(f(c.Get()).Get() == 10, "This should work.");
return 0;
}
您在这里违反的规则:
constexpr X a(x);
consetxpr
指针或 constexpr
引用是否必须引用具有静态存储持续时间的对象 - 这是其自身地址成为常量表达式的唯一方法。那是 而不是 x
的情况。
但是一旦你做到了(const
是多余的):
static constexpr int x = 10;
然后剩下的工作:
constexpr X a(x);
static_assert(f(a).Get() == 10, "This should work.");
具体规则为[expr.const]/11:
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
- if the value is an object of class type, each non-static data member of reference type refers to an entity that is a permitted result of a constant expression,
[...]
An entity is a permitted result of a constant expression if it is an object with static storage duration that either is not a temporary object or is a temporary object whose value satisfies the above constraints, or if it is a non-immediate function.
另见 of 。我可能应该关闭所有这些作为其中之一的欺骗?
我用 clang 和 gcc(主干版本)测试了以下代码。有人可以解释为什么使用普通 X 结构的情况不起作用,而按值捕获和使用 const 引用的包装器情况都可以正常工作。
struct X {
constexpr X(const int &v) : x(v) {}
constexpr int Get() const { return x; }
private:
const int& x;
};
constexpr X f(const X& r) {
return r;
}
struct Y {
constexpr Y(const int &v) : x(v) {}
constexpr int Get() const { return x; }
private:
const int x;
};
constexpr Y f(const Y& r) {
return r;
}
struct Wrap {
constexpr Wrap(const int& v) : x(v) {}
constexpr Y Get() const { return Y{x}; }
private:
const int x;
};
int main() {
constexpr const int x = 10;
/* this does not work for some reason
constexpr X a(x);
static_assert(f(a).Get() == 10, "This should work.");
*/
// This works.
constexpr Y b(x);
static_assert(f(b).Get() == 10, "This should work.");
// This also works.
constexpr Wrap c(x);
static_assert(f(c.Get()).Get() == 10, "This should work.");
return 0;
}
您在这里违反的规则:
constexpr X a(x);
consetxpr
指针或 constexpr
引用是否必须引用具有静态存储持续时间的对象 - 这是其自身地址成为常量表达式的唯一方法。那是 而不是 x
的情况。
但是一旦你做到了(const
是多余的):
static constexpr int x = 10;
然后剩下的工作:
constexpr X a(x);
static_assert(f(a).Get() == 10, "This should work.");
具体规则为[expr.const]/11:
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
- if the value is an object of class type, each non-static data member of reference type refers to an entity that is a permitted result of a constant expression,
[...]
An entity is a permitted result of a constant expression if it is an object with static storage duration that either is not a temporary object or is a temporary object whose value satisfies the above constraints, or if it is a non-immediate function.
另见