我正在尝试使用 constexpr 编写指向成员函数的指针的链表。主要是为了好玩,但它可能有一个有用的应用程序。
struct Foo;
using MethodPtr = void (Foo::*)();
struct Node
{
constexpr Node(MethodPtr method, const Node* next)
: Method(method)
, Next(next)
{}
constexpr Node Push(MethodPtr method)
{
return Node(method, this);
}
MethodPtr Method;
const Node* Next;
};
struct Foo
{
constexpr static Node GetMethods()
{
return Node{&Foo::Method1, nullptr}
.Push(&Foo::Method2)
.Push(&Foo::Method3);
}
void Method1() {}
void Method2() {}
void Method3() {}
};
int main(void)
{
constexpr Node node = Foo::GetMethods();
}
上面的代码在调用 GetMethods() 时在 main 中给出了以下错误:
const Node{MethodPtr{Foo::Method3, 0}, ((const Node*)(& Node{MethodPtr{Foo::Method2, 0}, ((const Node*)(& Node{MethodPtr{Foo::Method1, 0}, 0u}))}))}' is not a constant expression
有人能解释一下为什么这不是常量表达式吗?或者是否有替代/正确的方法来实现在编译时构建 PTMF 列表的目标?
编辑:我正在使用来自 avr-gcc 4.9.2 的 C++ 编译器。我将在另一个编译器上尝试这段代码。
最佳答案
您正在存储非静态存储持续时间的临时地址,这在常量表达式中是不允许的。此规则的当前版本在 [expr.const]/5 中(强调我的):
A constant expression is either a glvalue core constant expression whose value refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value is an object where, for that object and its subobjects:
each non-static data member of reference type refers to an entity that is a permitted result of a constant expression, and
if the object or subobject is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object ([expr.add]), the address of a function, or a null pointer value.
(C++11包含类似的规则(通过地址常量表达式的定义),但是常量表达式规则在被C++14通用化替换之前被多个DR改变了constexpr
,我今天真的不想做标准考古学。)
事实上,由于在 GetMethods()
中创建的每个临时 Node
除了返回的 Node
都在 处销毁;
,返回的 Node
将包含一个悬挂指针。
关于c++ - 有人能告诉我为什么这不是常量表达式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35544254/