2016-09-19 8 views
2

は、次のことを考えてみましょう:構文解析はどのように機能するのですか?型を完全または不完全にする要素は何ですか?

template <typename Alg> class AlgorithmTraits; 

template <class Alg> 
struct Heuristic { 
    using Neighbor = typename AlgorithmTraits<Alg>::Generator::Neighbor; 
}; 

template <class Alg, template <class> class HType> 
struct Generator { 
    using Neighbor = int; 
    HType<Alg> h_; 
}; 
template <class Alg> 
using GeneratorPolicy = Generator<Alg, Heuristic>; 

template <template <class> class InitialHeuristic_, 
      template <class> class Generator_> class Astar; 

template <template <class> class InitialHeuristic_, 
      template <class> class Generator_> 
struct AlgorithmTraits<Astar<InitialHeuristic_, Generator_>> { 
    using MyAlgorithm = Astar<InitialHeuristic_, Generator_>; 
    using InitialHeuristic = InitialHeuristic_<MyAlgorithm>; 
    using Generator = Generator_<MyAlgorithm>; 
}; 

template <template <class> class InitialHeuristic_, 
      template <class> class Generator_> 
class Astar { 
    using InitialHeuristic = typename AlgorithmTraits<Astar>::InitialHeuristic; 
    using Generator = typename AlgorithmTraits<Astar>::Generator; 
    //InitialHeuristic h_; // version 1 (does not compile) 
    Generator g_;   // version 2 (compiles) 
}; 

int main() { 
    Astar<Heuristic, GeneratorPolicy> a; (void)a; 
    return 0; 
} 

コメントで「バージョン2」と表記Astarクラスの定義にラインを見てください。 Astarmainのようにインスタンス化された場合、メンバーg_は、のインスタンス化であるタイプh_を持つタイプGeneratorPolicy<Astar>です。しかし、HeuristicNeighborエイリアスの宣言では、GeneratorPolicy<Astar>が完了する必要があります。私はそれが完全ではないと思います。なぜなら、コンパイラは今すぐ解析中ですからです。したがって、なぜコードがコンパイルされるのか混乱しています。

P.S. GeneratorPolicy<Astar>が完了したと答えると、バージョン1がどのようにコンパイルされないのか説明してください。そのバージョンのg++ 5.4.0のエラー出力は次のようになります。

temp.cpp: In instantiation of ‘struct Generator<Astar<Heuristic, GeneratorPolicy>, Heuristic>’: 
temp.cpp:17:72: required from ‘struct Heuristic<Astar<Heuristic, GeneratorPolicy> >’ 
temp.cpp:43:22: required from ‘class Astar<Heuristic, GeneratorPolicy>’ 
temp.cpp:48:39: required from here 
temp.cpp:23:16: error: ‘Generator<Alg, HType>::h_’ has incomplete type 
    HType<Alg> h_; 
       ^
temp.cpp:16:8: note: declaration of ‘struct Heuristic<Astar<Heuristic, GeneratorPolicy> >’ 
struct Heuristic { 

EDIT:アマデウスへおかげで、ここでは簡単なバージョンです:

template <typename Alg> 
struct Generator; 

template <typename Alg> struct Heuristic { 
    using Neighbor = typename Generator<Alg>::Neighbor; 
}; 

template <typename Alg> struct Generator { 
    using Neighbor = int; 
    Heuristic<Alg> h; 
}; 

int main() 
{ 
    Heuristic<int> x; // Version 1 - compile error 
    //Generator<int> x; // Version 2 - compile fine 
    (void)x; 
} 

は、しかし、私はまだはっきりと理由をバージョン2つのコンパイルを理解していません良い。

+3

コードは非常に複雑で読みにくく、把握が難しいです。 – sigy

+0

"不完全な型"は、通常、 'class Incomplete;'のような宣言と定義しか持たない 'class'や' struct'のような型です。 –

答えて

3

コードは非常に分かりにくいです。したがって、よりシンプルなバージョンを作成しました。

template <typename T> 
struct Bar; 

template <typename T> 
struct Foo 
{ 
    using a = typename Bar<T>::Type; 
}; 

template <typename T> 
struct Bar 
{ 
    using Type = int; 
    Foo<T> x; 
}; 

int main() 
{ 
    //Foo<int> x; // Version 1 - compile error 
    Bar<int> x; // Version 2 - compile fine 
    (void)x; 
} 

タイプが完全に定義される前に使用する場合、不完全タイプが発生します。バージョン1では、あなたはに簡単ですのみBar<int>::Typeを使用しているFoo<int>を、定義し、あなたはその後、Bar<int>を定義されており、バージョン2の場合はBar<int>

でそれを使用したいと同時に、Foo<int>を定義しようとしています定義を完了してください。

+0

あなたの単純なバージョンでは問題はうまく解決されます。私はあなたの答えの最後のいくつかの単語を理解していませんでした: "これは、定義を完了するのは簡単です"。あなたは詳細を教えていただけますか? – AlwaysLearning

+0

@AlwaysLearning私は解析の専門家ではありません。 2番目のバージョンでは 'Foo 'をインスタンス化するときに、 'Bar 'はそれ自体をリファイニングしていないと言っていますが、別名( 'Bar :: Type') – Amadeus

+0

のみを使用しています。将来このような問題が設計段階で発生します。誰でも? – AlwaysLearning

関連する問題