C++ constexpr 自动成员函数。铛问题?
C++ constexpr auto member function. Clang issue?
#include <utility>
struct A {
constexpr auto one(int a) {
return std::integral_constant<int, _data[a]>{};
}
constexpr int two(int a) const {
return _data[a];
}
int _data[10];
};
int main() {
constexpr auto ex = A{{1,2,3,4,5,6,7,8,9,10}};
std::integral_constant<int, ex.two(3)> b{};
}
上面的代码不会在trunk Clang中编译。错误在 one()
成员函数中,并表示:
cc.cpp:57:44: note: implicit use of 'this' pointer is only allowed
within the evaluation of a call to a 'constexpr' member function.
显然,该函数被标记为 constexpr
,如果您注释掉 one()
成员,一切都可以正常编译,因此我们显然能够从 ex
,但不是直接来自 struct
?看起来,当我需要 auto
return 类型推导时,它失败并声称函数不是 constexpr
?
这是预期的吗?我觉得这应该不是问题,如果这是预期的行为,我会感到惊讶。
constexpr
函数可以在编译时和 运行 时调用。
- 如果您可以省略
constexpr
并获得适当的普通函数,则带有 constexpr
函数的代码是格式良好的。换句话说,它 必须 编译为 运行 时间函数。
- 如果
constexpr
函数的主体无法在编译时计算,它仍然会被编译,但您不能在模板参数等编译时上下文中使用它。
- 如果在
constexpr
对象上调用 constexpr
方法,this
被认为是 constexpr。
在 one
的情况下它是错误的,因为当它在 运行 时被编译为 运行 时,_data[a]
被认为是 运行-时间表达式,因为 a
不是常量表达式,即使 this
和 this->_data
是。
在 two
的情况下它编译得很好,因为它在 运行 时工作正常,并且在编译时 this
是 constexpr
和 a
,因此 this->_data[a]
是 constexpr
,一切正常。
如果你在 [dcl.constexpr]/7 中考虑这个语句:
A call to a constexpr
function produces the same result as a call to an equivalent non-constexpr
function in all respects except that a call to a constexpr
function can appear in a constant expression.
考虑非 constexpr
等效函数 A::one()
。 _data[a]
不能用于常量表达式(作为非类型模板参数),因为它会涉及 this
的计算,来自 [expr.const]:
A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the
abstract machine (1.9), would evaluate one of the following expressions:
(2.1) — this
(5.1.1), except in a constexpr
function or a constexpr
constructor that is being evaluated as
part of e;
由于非 constexpr
等价物格式错误,constexpr
函数给出相同结果是合理的。
另一方面,two()
是一个结构良好的成员函数,与 constexpr
无关,并且您对 ex.two(3)
的使用作为常量表达式是有效的 - 这就是它编译的原因。
#include <utility>
struct A {
constexpr auto one(int a) {
return std::integral_constant<int, _data[a]>{};
}
constexpr int two(int a) const {
return _data[a];
}
int _data[10];
};
int main() {
constexpr auto ex = A{{1,2,3,4,5,6,7,8,9,10}};
std::integral_constant<int, ex.two(3)> b{};
}
上面的代码不会在trunk Clang中编译。错误在 one()
成员函数中,并表示:
cc.cpp:57:44: note: implicit use of 'this' pointer is only allowed
within the evaluation of a call to a 'constexpr' member function.
显然,该函数被标记为 constexpr
,如果您注释掉 one()
成员,一切都可以正常编译,因此我们显然能够从 ex
,但不是直接来自 struct
?看起来,当我需要 auto
return 类型推导时,它失败并声称函数不是 constexpr
?
这是预期的吗?我觉得这应该不是问题,如果这是预期的行为,我会感到惊讶。
constexpr
函数可以在编译时和 运行 时调用。- 如果您可以省略
constexpr
并获得适当的普通函数,则带有constexpr
函数的代码是格式良好的。换句话说,它 必须 编译为 运行 时间函数。 - 如果
constexpr
函数的主体无法在编译时计算,它仍然会被编译,但您不能在模板参数等编译时上下文中使用它。 - 如果在
constexpr
对象上调用constexpr
方法,this
被认为是 constexpr。
在 one
的情况下它是错误的,因为当它在 运行 时被编译为 运行 时,_data[a]
被认为是 运行-时间表达式,因为 a
不是常量表达式,即使 this
和 this->_data
是。
在 two
的情况下它编译得很好,因为它在 运行 时工作正常,并且在编译时 this
是 constexpr
和 a
,因此 this->_data[a]
是 constexpr
,一切正常。
如果你在 [dcl.constexpr]/7 中考虑这个语句:
A call to a
constexpr
function produces the same result as a call to an equivalent non-constexpr
function in all respects except that a call to aconstexpr
function can appear in a constant expression.
考虑非 constexpr
等效函数 A::one()
。 _data[a]
不能用于常量表达式(作为非类型模板参数),因为它会涉及 this
的计算,来自 [expr.const]:
A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:
(2.1) —this
(5.1.1), except in aconstexpr
function or aconstexpr
constructor that is being evaluated as part of e;
由于非 constexpr
等价物格式错误,constexpr
函数给出相同结果是合理的。
另一方面,two()
是一个结构良好的成员函数,与 constexpr
无关,并且您对 ex.two(3)
的使用作为常量表达式是有效的 - 这就是它编译的原因。