Я вижу несколько решений, связанных со связанными списками, но все они, боюсь, уродливы;)
Однако, учитывая, что все узлы списка принадлежат общему объекту 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
И да, это работает.
person
Matthieu M.
schedule
16.12.2012
Size
? И вы говорите, что размер варьируется от узла к узлу, это не константа для всех узлов в списке? - person John Kugelman   schedule 16.12.2012