3

Node次のようなクラスを実装しました。

template<unsigned int Size>
class Node
{
    private:
        Eigen::Matrix<float, Size, Size> m_matrix;

        Node<?> *m_previousNode;
        Node<?> *m_nextNode;
};

テンプレート引数によって次元が設定されるメンバー変数があります。また、これは重要な部分であり、前のノードと次のノードへのポインターを格納します(それ自体のサイズとは異なるサイズを持つことができます)。

これで、クラスに格納したいさまざまなサイズのこのクラスのノードが固定されましたNetwork。最初は3次元である可能性があります。

template<unsigned int S0, unsigned int S1, unsigned int S2>
class Network
{
    private:
        Node<S0> *m_firstNode;
        Node<S1> *m_secondNode;
        Node<S2> *m_thirdNode;
};

これは私がそれをインスタンス化したい方法です:

Network<10, 20, 5> network;

ご覧のとおり、ノードの数と各ノードのサイズは固定されています。後で変更することはできません。

Node<?> *私の質問は、前のノードと次のノード(上記のコード内)へのポインターをどのように格納できるかです。

私は最初、次のようにテンプレート引数リストを拡張することを考えました。

template<unsigned int PreviousSize, unsigned int Size, unsigned int NextSize>
class Node
private:
    Eigen::Matrix<float, Size, Size> m_matrix;

    Node<?, PreviousSize, Size> *m_previousNode;
    Node<Size, NextSize, ?> *m_nextNode;

しかし、明らかに、前のノードの前のノードのサイズを知る必要があり、同じ問題が発生します。それでも、を入力できません?

これを解決する方法はありますか?

4

1 に答える 1

0

リンクリストを含むいくつかの解決策を見ることができますが、それらはすべて、恐縮ですが、お尻が醜いです;)

ただし、リストのすべてのノードが共通のエンティティ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

そして、はい、それは動作します。

于 2012-12-16T13:01:09.010 に答える