2016-09-19 44 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