2016-09-19 29 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類的定義。當Astar被例示爲如在main中時,成員g_是類型GeneratorPolicy<Astar>,其具有成員h_的類型,其是Heuristic的實例化。但是,似乎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 { 

編輯:由於艾瑪迪斯,這裏是一個簡單的版本:

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'或'struct',它只有一個聲明而沒有定義,就像'class Incomplete;'一樣。 –

回答

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版,你想在同一時間定義Foo<int>想在Bar<int>

使用它在版本2.您定義Bar<int>,然後的情況下,確定Foo<int>即只使用Bar<int>::Type,這是很容易完成定義。

+0

更簡單的版本可以很好地捕捉問題。我不明白你答案的最後幾個字:「這很容易完成定義」。你能否詳細說明一下? – AlwaysLearning

+0

@AlwaysLearning我不是解析專家。但我會說在第二個版本中,'Bar '在實例化'Foo '時沒有自動更新,而只使用別名('Bar :: Type') – Amadeus

+0

我真的很想知道避免的確切原因這種問題在未來的設計階段就會出現。任何人? – AlwaysLearning

相關問題