C++中运行时对象的非静态成员函数指针constexpr求值机制探究
为什么非constexpr对象的成员函数指针调用能作为编译期常量?
你的代码里obj没有声明为constexpr,但(obj.*funcPtr)(12)却能作为模板参数(要求编译期常量)正常编译,核心原因可以拆解为以下几点:
目标成员函数是无状态的constexpr函数
你定义的myFunction是constexpr成员函数,而且它的实现完全不依赖MyClass对象的任何非静态数据成员——仅接收参数value并返回其两倍值。这意味着调用该函数时,无论对象本身是什么状态,只要传入的参数是编译期常量,函数的返回值就能在编译期确定。成员函数指针是constexpr
funcPtr被声明为constexpr,它指向myFunction的地址在编译期就已固定,不会在运行期发生变化,这为编译期求值提供了稳定的调用目标。C++标准对常量表达式的规则放宽
在C++17及后续标准中,常量表达式的求值规则有所放宽:对于非静态成员函数的调用,只要满足以下条件,即使调用的对象不是constexpr,表达式仍可被视为常量表达式:- 成员函数本身是
constexpr - 所有函数实参都是常量表达式
- 函数执行过程中未访问对象的非静态数据成员(或访问的成员本身是编译期可确定的)
- 函数执行无未定义行为
- 成员函数本身是
反过来验证:如果myFunction依赖对象的非静态成员,比如:
class MyClass { int num = 3; public: constexpr int myFunction(int value) { return value * num; } };
此时(obj.*funcPtr)(12)就无法作为编译期常量——因为obj不是constexpr,它的num成员值在编译期无法确定,编译器会直接报错。
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

