我有以下代码:
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.7.0;
pragma experimental ABIEncoderV2;
contract VenueRegistry{
struct Queue{
uint head;
uint tail;
mapping(uint => address) queue;
}
struct Venue{
uint id;
Queue queue;
}
mapping (uint => Venue) public venues;
}我得到以下错误:
TypeError:公共状态变量不允许内部或递归类型。测绘(uint =>场馆)公共场所;
因此,我把venues变成了私有的,并写了一个getter:
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.7.0;
pragma experimental ABIEncoderV2;
contract VenueRegistry{
struct Queue{
uint head;
uint tail;
mapping(uint => address) queue;
}
struct Venue{
uint id;
Queue queue;
}
mapping (uint => Venue) venues;
function getVenue(uint _index) public view returns(Venue memory){
return venues[_index];
}
}然后,我得到以下错误:
只允许库在公共或外部函数中使用映射类型。
问题似乎在于struct Queue内部的映射。当我删除映射时,它就能工作了。是否有一种方法可以让嵌套的结构中包含映射?
发布于 2020-05-22 16:17:05
问题是您在两个地方使用了不兼容数据结构的public。
首先,这一行:
pragma solidity >=0.4.22 <0.7.0;
这使得无法复制您的结果,因为没有人知道您正在使用的编译器。出于这个原因,在主合同中具体说明,强制执行某个版本是很好的。如果继承的合同、库等具有更大的灵活性,这是可以的,因为主契约仍然会强制解决这个问题。
我用了Solc 6.6。
public对状态变量做了几件事。如果你想要所有的东西,这是非常方便的,但是如果你不想要所有的东西,你可以手动编码。其中之一是一个看起来像function variable(args) public returns(...的“免费”getter。
它适用于标量变量、数组和映射,因此uint public x;是not的,uint[] public x;是可以的,但是myComplexStructWithMoreIndexedStuff[] public x;是不兼容的。总之,这是因为编译器不确定如何为您构造getter。
没问题。只需将其设置为私有或内部,并编写自己的getter函数以请求参数、获取元素并返回响应。
所以:
mapping (uint => Venue) private venues;
同样,public和您试图返回一个包含内部映射的结构。一个结构本身就足以导致与public一起出现的问题。
对于结构、数组和映射,函数参数是存储指针,意味着对存储位置的32字节引用,而不是实际数据。对于契约本身信任的内部和私有上下文来说,这是很好的。但是,存储指针不能传入或输出。
请注意,系统不会对数据进行迭代以产生关于变量值的冗长响应,而且可能永远不会,因为这将导致O(n)复杂性--链上的高CPU和I/O活动,而这是您不想要的。由于它不能返回数组的所有元素,也不能返回指向存储的简单指针,所以它无能为力。
可以重写它以返回一个元素,以及该元素的任何内容,如下所示:
function getVenueQueueElement(uint id, uint row) public view returns(address) {
return venues[id].queue[row];
}您可以考虑一种更好的数据结构,以便于枚举存在的场所和队列成员,这样客户端就不应该请求无稽之谈和契约对象。
看看这个更新的解释器,一定要阅读第1和第2部分,以真正理解正在发生的事情和解决的问题:https://medium.com/robhitchens/solidity-crud-epilogue-e563e794fde
它在内部使用存储指针。它们是神秘的东西,所以这可能会有帮助:https://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089
希望能帮上忙。
https://ethereum.stackexchange.com/questions/83625
复制相似问题