constexpr 链表 - 从 const X* 到 X* 的转换无效

constexpr linked list - invalid conversion from const X* to X*

本文关键字:转换 无效 链表 const constexpr      更新时间:2023-10-16

这是我尝试创建一个简单的 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链接

直接错误很容易修复:

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

抱怨是current = current->next;正在为Node *分配Node const*,所以不要这样做。

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

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

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

正如@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不是正确的选择。

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