3

グラフ用のオープン ソース クラス ライブラリを見つけました。プロジェクトに含めたとき、多くのエラーがあり、それらを修正しようとしました。しかし、解決できないコンパイルエラーがあります。

基本クラス:

template <typename K, typename W, typename T>
class _base_graph
{
//... 

protected:
    std::map<K, T> nod;
    std::list<edge> edg;
};

派生クラス:

template <typename K, typename T = void*>
        class graph : public _base_graph<K, void*, T>
{
//...
public:
    void add_edge(const K& k1, const K& k2);
};

メソッド本体:

template <typename K, typename T>
void graph<K, T>::add_edge(const K& k1, const K& k2)
{
    if (nod.find(k1) == nod.end() || nod.find(k2) == nod.end()) // <-- error!!
        throw std::string("add_edge: Node does not exist");

    // ...
}

しかし、私の gcc コンパイラはエラーを表示します:

エラー: 'nod' はこのスコープで宣言されていません

このオンライン コンパイラで mycode を見つけてテストできます。

4

2 に答える 2

8

あなたが必要

this->nod.find(k2);

また

_base_graph<K, void*, T>::nod.find ....;

基本クラスと派生クラスはテンプレートであり、コードnodでは は非依存の名前であるため、graphの宣言の時点で参照されます。これは、2 フェーズ ルックアップの最初のフェーズです。この段階では、コンパイラは (標準の名前検索規則に従っている限り)nod意味を知ることができません。これは、コンパイラが第 2 フェーズまで基本クラスを考慮しないためです。nodそのため、第 2 フェーズで検索する必要があることをコンパイラに伝える必要があります。これを行うにnodは、上記のいずれかの形式を使用して、それが基底クラスにあることを明示的に伝えます。

この動作の理由は、派生クラスの定義_base_graph<K, void*, T>::の時点で、名前を追加したり非表示にしたりするテンプレートの特殊化を可能にするために、何が含まれているかを知ることができないためです。したがって、上記のトリックにより、すべての情報が利用可能になったときに、派生クラスのインスタンス化の時点で名前が検索されるようになります。

要約すると、ここには 2 つの問題があります。

  1. nod依存名ではないため、最初のフェーズで検索されます。
  2. を宣言した基本クラス テンプレートはnod、第 2 フェーズまで使用できないため、名前を解決できません。

this->nodorを使用すること_base_graph<K, void*, T>::nodで、従属名を明示的に処理し、ルックアップを第 2 フェーズで強制的に実行します。

ポイント 7 から 10 を参照してください

@DavidRodriguez-dribeas に感謝します。2 フェーズ ルックアップの細かい点を明確にしてくれました。

于 2012-11-13T11:08:45.707 に答える
3

nod依存ベース (テンプレート パラメーターに依存するもの) のメンバーです。ベースの名前で呼び出しを修飾する必要があり_base_graph<K, void*, T>::nodますthis->nod

あるいは、関数またはクラスのスコープusing _base_graph<K, void*, T>::nodで名前を持ち込むこともできます。

于 2012-11-13T11:11:33.117 に答える