リンクリストを含むいくつかの解決策を見ることができますが、それらはすべて、恐縮ですが、お尻が醜いです;)
ただし、リストのすべてのノードが共通のエンティティNetwork
、つまりマジックカードに属していることを考えると。リストのアイデアを捨てて、代わりにネットワーク内の「配置された」ノードを目指すと、はるかに簡単になります。
template <typename Network, unsigned Index, unsigned Size>
class Node {
public:
private:
Network* m_network;
Eigen::Matrix<float, Size, Size> m_matrix;
}; // class Node
そしてネットワーク:
template <unsigned Size0, unsigned Size1, unsigned Size2>
class Network {
public:
template <unsigned Index>
auto access() -> decltype(m_nodes.get<Index>()) {
return m_nodes.get<Index>();
}
template <unsigned Index>
auto get() const -> decltype(m_nodes.get<Index>()) {
return m_nodes.get<Index>();
}
private:
std::tuple< Node<Network, 0u, Size0>,
Node<Network, 1u, Size1>,
Node<Network, 2u, Size2>> m_nodes;
};
そして最後に、反復?
template <typename Network, unsigned Index, unsigned Size>
auto Node<Network, Index, Size>::prev() -> decltype(m_network->access<Index-1>()) {
return m_network->access<Index-1>();
}
template <typename Network, unsigned Index, unsigned Size>
auto Node<Network, Index, Size>::next() -> decltype(m_network->access<Index+1>()) {
return m_network->access<Index+1>();
}
さて、ここで鶏が先か卵が先かという問題が少しあることを除けば、クラスNode
内の定義をネストすることで、カンニングをすることができます。Network
そして、私はそれを行うかもしれませんが、反復が常にネットワーククラスから開始されるべきであることを受け入れるのはなぜですか?
最後に、これが私が提案するものです:
template <unsigned Size>
class Node {
public:
// ...
private:
Eigen::Matrix<float, Size, Size> m_matrix;
};
template <unsigned Size>
std::ostream& operator<<(std::ostream& out, Node<Size> const&) {
return out << "Node<" << Size << ">";
}
template <unsigned S, unsigned... Sizes>
class Network {
private:
// Hack for gcc, using m_nodes in decltype requires that it's already been declared
typedef std::tuple< Node<S>, Node<Sizes>... > Nodes;
Nodes m_nodes;
public:
static constexpr unsigned Size() { return sizeof...(Sizes) + 1; }
template <unsigned Index>
auto access() -> decltype(std::get<Index>(this->m_nodes)) {
return std::get<Index>(this->m_nodes);
}
template <unsigned Index>
auto get() const -> decltype(std::get<Index>(this->m_nodes)) {
return std::get<Index>(this->m_nodes);
}
}; // class Network
もちろん、はNode
もはやその位置を知りませんが、イテレータでそれをまとめることができます。
template <typename Network, unsigned Index>
class NetworkIterator {
private:
// Hack for gcc, using m_network in decltype requires that it's already been declared
Network& m_network;
public:
static_assert(Index < Network::Size(), "Index cannot exceed network size by more than one");
NetworkIterator(Network& n): m_network(n) {}
auto element() -> decltype(this->m_network.template access<Index>()) {
return m_network.template access<Index>();
}
template <unsigned U = Index - 1>
NetworkIterator<Network, U> prev() {
return NetworkIterator<Network, U>(m_network);
}
template <unsigned U = Index + 1>
NetworkIterator<Network, U> next() {
return NetworkIterator<Network, U>(m_network);
}
}; // class NetworkIterator
そして、はい、それは動作します。