【问题标题】:constexpr linked list - invalid conversion from const X* to X*constexpr 链表 - 从 const X* 到 X* 的无效转换
【发布时间】:2017-07-10 13:54:11
【问题描述】:

这是我尝试创建一个简单的 constexpr 链表 -

struct Node
{
    constexpr Node(const int n, Node const* next = nullptr)
        : value(n), next(next) {}
    constexpr Node push(const int n) const { return Node(n, this); }

    int value;
    Node const* next;
};

constexpr auto getSum(Node n) {
    int sum = 0;
    Node *current = &n;
    while(current != nullptr) {
        sum += current->value;
        current = current->next;
    }
    return sum;
}

int main() {
    constexpr Node a(0);
    a.push(1);
    a.push(22);
    constexpr auto result = getSum(a);
    return result;
}

在编译这个程序时,出现如下错误

prog.cc: In function 'constexpr auto getSum(Node)':
prog.cc:16:28: error: invalid conversion from 'const Node*' to 'Node*' [-fpermissive]
         current = current->next;
                   ~~~~~~~~~^~~~
prog.cc: In function 'int main()':
prog.cc:25:35:   in constexpr expansion of 'getSum(a)'
prog.cc:16:28: error: conversion of 'const Node*' null pointer to 'Node*' is not a constant expression

我应该如何继续解决这个问题并生成这样的链表?这是Wandbox Link在线查看执行。

【问题讨论】:

  • 哇,我不认为你在做什么......
  • constexpr 对象仍然遵循抽象机器的规则。所有对push 的调用都会返回一个立即过期的临时文件。即使您修复了错误,您的列表也永远不会增加。
  • 该死的..这一定是我见过最多的constconstexpr了..

标签: c++ data-structures c++14 constexpr c++17


【解决方案1】:

直接错误很容易修复:

  Node const *current = &n;
  //   ^^^^^

抱怨是current = current->next;Node const* 分配给Node *,所以不要那样做。

这样做将使您的程序编译但打印0,因为push 都不会调用修改后的a。您也不能将push 的结果存储为constexpr,因为自动局部变量a 的地址不是常量表达式。

但是,您可以形成一个临时节点的链表并立即使用它:

constexpr auto result = getSum(a.push(1).push(22).push(19)); // OK, 42

【讨论】:

    【解决方案2】:

    正如@hg_git 在您帖子的评论中指出的那样,constexpr 链接列表是不可能的。

    我清理了你的代码有一个有用的错误。

    #include <iostream>
    
    struct Node
    {
        constexpr Node(const int n, Node * next = nullptr)
            : value(n), next(next) {}
        constexpr Node push(const int n) { return Node(n, this); }
    
        int value;
        Node * next;
    };
    
    constexpr auto getSum(Node n) {
        int sum = 0;
        Node *current = &n;
        while(current != nullptr) {
            sum += current->value;
            current = current->next;
        }
        return sum;
    }
    
    int main() {
        constexpr Node a(0);
        a.push(1);
        a.push(22);
        constexpr auto result = getSum(a);
        return result;
    }
    

    给这个

    main.cpp: In function 'int main()':
    main.cpp:25:13: error: passing 'const Node' as 'this' argument discards qualifiers [-fpermissive]
         a.push(1);
                 ^
    main.cpp:7:20: note:   in call to 'constexpr Node Node::push(int)'
         constexpr Node push(const int n) { return Node(n, this); }
                        ^~~~
    main.cpp:26:14: error: passing 'const Node' as 'this' argument discards qualifiers [-fpermissive]
         a.push(22);
                  ^
    main.cpp:7:20: note:   in call to 'constexpr Node Node::push(int)'
         constexpr Node push(const int n) { return Node(n, this); }
    

    如您所见,即使关键字const 不存在,const 参数仍然存在一些问题。这是因为 constexpr 是在编译时计算的。从而使它们在运行时不可变。

    链表可以在运行时改变;如果您为每个示例添加或删除一个节点。 所以constexpr在这种情况下不是正确的选择。

    编辑: 这是您的代码的live demo,从constexpr 清除。我添加了一些评论,如果您不了解行或功能,请随时询问。

    【讨论】:

    • 有可能,我们只需要注意临时对象的生命周期 :)
    猜你喜欢
    • 1970-01-01
    • 2012-09-08
    • 1970-01-01
    • 2011-02-10
    • 2012-05-13
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多