例を挙げて尋ねるのが最も簡単な方法だと思います。次のタイプがあるとします。
class Node
{
// make noncopyable
Node(const Node& ref) = delete;
Node& operator=(const Node& ref) = delete;
// but moveable
Node(Node&& ref) = default;
Node& operator=(Node&& ref) = default;
// we do not have a default construction
Node() = delete;
Node(unsigned i): _i(i) {}
unsigned _i;
};
今、これらのノードのいくつかを std::array に保存したいと思います:
template<unsigned count>
class ParentNode
{
std::array<Node,count> _children;
ParentNode()
// i cannt do this, since i do not know how many nodes i need
// : _children{{Node(1),Node(2),Node(3)}}
: _children() // how do i do this?
{}
};
コメントで述べたように、質問は次のとおりです。これを行うにはどうすればよいですか? 子に渡される unsigned は、子が格納されている配列のインデックスでなければなりません。しかし、より一般的なソリューションも非常に高く評価されています!
私が見つけた次の解決策は、より複雑な型の未定義の動作になる可能性があります。明確に定義された適切な解決策については、受け入れられた回答を参照してください。
template<unsigned count>
class ParentNode
{
public:
// return by value as this will implicitly invoke the move operator/constructor
std::array<Node,count> generateChildren(std::array<Node,count>& childs)
{
for (unsigned u = 0; u < count; u++)
childs[u] = Node(u); // use move semantics, (correct?)
return std::move(childs); // not needed
return childs; // return by value is same as return std::move(childs)
}
std::array<Node,count> _children;
ParentNode()
// i cannt do this, since i do not know how many nodes i need
// : _children{{Node(1),Node(2),Node(3)}}
: _children(generateChildren(_children)) // works because of move semantics (?)
{}
};
ParentNode<5> f;
コードはコンパイルされます。しかし、それが私が期待することをするかどうかはわかりません。たぶん、移動セマンティクスと右辺値参照に詳しい人がコメントを追加できます:-)