我可以看到几个涉及链表的解决方案,但它们都很丑陋;)
然而,考虑到列表的所有节点都属于一个共同实体“网络”,我认为这是我们的魔法卡。如果我们放弃列表的想法,而是针对网络中的“定位”节点,那么问题就变得容易得多!
template <typename Network, unsigned Index, unsigned Size>
class Node {
public:
private:
Network* m_network;
Eigen::Matrix<float, Size, Size> m_matrix;
};
而且网络:
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:
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);
}
};
当然,一个
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
没错,它管用。
Size
参数控制的是哪种数据结构的大小?您是说大小因节点而异,在列表中并不是所有节点都是常量大小吗? - John Kugelman