c++ - 有人能告诉我为什么这不是常量表达式吗?

标签 c++ c++11 constexpr

我正在尝试使用 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/

相关文章:

c++ - 如何将 wcstombs 转换为 wcstombs_s

c++ - 无法从另一个函数 C++ 类访问成员

c++ - 找到数字与给定数字相乘的最小数字

c++11 - 迭代 std::array 中的记录

c++ - 为什么在使用静态 constexpr 成员构造时 std::make_shared 与 new 不同?

c++ - std::unique_lock::release 的用例是什么?

c++ - 无法使用 qss 文件设置样式表属性

c++ - "Bad file descriptor"在子线程中访问套接字描述符时

c++ - 为什么我应该更喜欢类中的 static constexpr int 而不是类级整数常量的枚举?

c++ -::std::function 的 constexpr 版本