內部帶有映射的嵌套結構
我有以下程式碼:
// 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 => Venue)公共場所;
所以我做了
venues
私有並寫了一個吸氣劑:// 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
. 當我刪除映射時,它可以工作。有沒有辦法讓嵌套結構內部帶有映射?
問題是您
public
在兩個地方使用了不兼容的資料結構。首先,這一行:
pragma solidity >=0.4.22 <0.7.0;
它使您無法複製您的結果,因為沒有人確定您使用的是什麼編譯器。出於這個原因,最好在主契約中具體說明,強制某個版本。如果繼承的合約、庫等具有更大的靈活性也沒關係,因為主合約仍然會強制執行該問題。
我使用了 Solc 6.6。
在第 16 行:
public
對狀態變數做幾件事。這是全有或全無 - 如果您想要所有內容,非常方便,但如果您不想要所有內容,您可以手動編寫程式碼。其中之一是看起來像function variable(args) public returns(...
.它適用於標量變數、數組和映射,所以
uint public x;
可以,uint[] public x;
也可以,但myComplexStructWithMoreIndexedStuff[] public x;
不兼容。總之,這是因為編譯器不確定如何為您構造 getter。沒問題。只需將其設為私有或內部並編寫您自己的 getter 函式以請求參數、獲取元素並返迴響應。
所以:
mapping (uint => Venue) private venues;
在第 18 行:
同樣,
public
您試圖返回一個內部帶有映射的結構。單獨的 struct 就足以與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
希望能幫助到你。