将struct memory []内存类型复制到尚不支持的存储

时间:2018-03-18 08:27:24

标签: solidity smartcontracts

如何在下面的代码示例中将新的空Parent实例添加到父项列表中?我一直在

UnimplementedFeatureError: Copying of type struct Test.Child memory[] memory
to storage not yet supported.

最小例子:

contract Test {
  struct Child { } 
  struct Parent { Child[] children; }

  Parent[] parents;

  function test() {
    parents.push(Parent(new Child[](0)));
  }
}

2 个答案:

答案 0 :(得分:8)

你无法真正做到你想要用动态数组做的事情。您需要稍微改变一下方法才能使其发挥作用。

contract Test {
  struct Child { } 
  struct Parent { 
      mapping(uint => Child) children;
      uint childrenSize;
  }

  Parent[] parents;

  function testWithEmptyChildren() public {
      parents.push(Parent({childrenSize: 0}));
  }

  function testWithChild(uint index) public {
      Parent storage p = parents[index];

      p.children[p.childrenSize] = Child();
      p.childrenSize++;
  }
}

如果您需要在合同中的其他位置迭代Parent.childrenSize,请使用Parent.children

或者,您可以增加parents数组的大小并使用Solidity的默认零值。

contract Test {
  struct Child { } 
  struct Parent { Child[] children; }

  Parent[] parents;

  function test() public {
      parents.length++;
      Parent storage p = parents[parents.length - 1];

      Child memory c;

      p.children.push(c);
  }
}

答案 1 :(得分:1)

如果子数组类型是另一种结构,则不起作用(至少从Solidity 0.4.24开始),但如果子数组类型是诸如uint256之类的原始类型,则它起作用。

因此,如果您有

struct Child {
  uint256 x;
  bytes32 y;
}

然后您可以定义:

struct Parent {
  uint256[] childXs;
  bytes32[] childYs;
}

然后您可以写:

parents.push(Parent({
    childXs: new uint256[](0),
    childYs: new bytes32[](0)
}));

(当您要将结构体数组作为参数传递给公共函数时,可以采用相同的解决方法。)

这不理想,但是可以。

P.S。实际上(如果您使用的是原始数组子级),您可以编写:

Parent memory p;
parents.push(p);