1

グラフを表すこれらのクラスを作成しました。

class Node{

  public:
    typedef std::vector<Node>::iterator iterator;
    iterator begin() {return neigh.begin();}
    iterator end() {return neigh.end();}

  public:
    Node(std::string n) : name(n) {}

    std::string getName() {return name; }

    void addNeigh(Node n){
      neigh.push_back(n);
    } 

  private:
    std::string name;
    std::vector<Node> neigh;
};

class Map{

  public:
    typedef std::vector<Node>::iterator iterator;
    iterator begin() {return nodes.begin();}
    iterator end() {return nodes.end();}

  public:
    Map(std::string n) : map_name(n) {}

    void addNode(Node n){
      nodes.push_back(n);
    }


    std::string getName() { return map_name; }
    int getNumNodes() {return nodes.size();}

  private:
    std::string map_name;
    std::vector<Node> nodes;

};

printGraph次に、特性を使用していくつかのグラフ情報を出力する関数を書きたいと思います:

template<typename T>
struct GraphTraits{

};

template<>
struct GraphTraits<Map>{

  typedef Map::iterator node_iterator;

  static node_iterator node_begin(Map map){ return map.begin();}
  static node_iterator node_end(Map map) { return map.end();}

  static std::string getName(Map m) {return m.getName();}

};

template<typename T>
void printGraph(T t){
  std::cout << std::endl 
            << "--------------------------------------" << std::endl  
            << "|             printGraph             |" << std::endl  
            << "--------------------------------------" << std::endl;
  std::cout << "Graph name: " << GraphTraits<T>::getName(t) << std::endl;

  for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
        it != e; ++it) {
          std::cout<< (*it).getName() << std::endl; }
}

このコードをコンパイルしようとすると、次のエラーが発生します。

grafo.cpp:75:37: error: expected ';' in 'for' statement specifier
  for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
                                    ^
grafo.cpp:75:37: error: use of undeclared identifier 'it'
grafo.cpp:75:73: error: use of undeclared identifier 'e'
  for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
                                                                        ^
grafo.cpp:76:9: error: use of undeclared identifier 'it'
        it != e; ++it) {
        ^
grafo.cpp:76:15: error: use of undeclared identifier 'e'
        it != e; ++it) {
              ^
grafo.cpp:76:16: error: expected ')'
        it != e; ++it) {
               ^
grafo.cpp:75:6: note: to match this '('
  for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
     ^
grafo.cpp:76:20: error: use of undeclared identifier 'it'
        it != e; ++it) {
                   ^
grafo.cpp:75:23: error: unexpected type name 'node_iterator': expected expression
  for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
                      ^
grafo.cpp:104:3: note: in instantiation of function template specialization 'printGraph<Map>' requested here
  printGraph(mappa);
  ^

私はうまく解決してコンパイルすることができます:

for(GraphTraits<T>::node_iterator....

と:

for(GraphTraits<Map>::node_iterator....

しかし、これはprintGraphその一般性を失います。

誰かが問題を解決するためのヒントを教えてくれますか?

一般的に言えば、特性を使用してデータ型の定義を強制することは可能ですか? つまり:

template<typename T>
struct ATraits{
 -> type "iterator" must be defined
};

すべての専門化が定義する必要があるように:

typedef ..something.. iterator;
4

1 に答える 1

4

typenameキーワードの使用を忘れています。

ではGraphTraits<Map>::node_iterator、コンパイラはどの特殊化GraphTraitsが使用されているかを認識しており、それnode_iteratorが typedef であることを把握できます。

では、まだ知られていないGraphTraits<T>::node_iteratorため、どの特殊化が使用されるかわかりません。したがって、それは型ではなくメンバー変数であるTと想定しています。node_iteratorこの仮定を修正する必要があります。言うtypename GraphTraits<T>::node_iterator

typedef を提供するためにすべての特殊化を要求するにはGraphTraits、「概念」が必要です。これは C++11 用に提案されましたが、将来のバージョンまで延期する必要がありました。したがって、今日の C++ では不可能です。ただし、実際に USE を実行するたびにprintGraph(正式には、関数テンプレートの各テンプレート関数インスタンスのインスタンス化中printGraph<T>)、コンパイラはそれがGraphTraits<T>::node_iterator実際に型であるかどうかを再確認します (これは、Tオーバーロードの解決を認識して実行できるためです)。

于 2012-09-17T15:26:54.610 に答える