2014-12-31 6 views
2

나는 다양한 유형의 이진 검색 트리 (클래식, 스플레이, 리브 블랙, avl, 트랩, 랜덤 화 등)를 프로그래밍하고 있습니다.미분과 templatized의 차이점은 무엇입니까? (문맥을보십시오)

각 트리 유형에 대해 노드 유형, 키 유형 및 키 간의 기능 비교를 매개 변수로받는 일반 클래스를 정의합니다. 예를 들어, P는 AVL 트리에 대한 다음과 같은 클래스를 정의 (및 구현) :이 방법에 대한

template <template <typename> class NodeType, typename Key, class Compare> 
class Gen_Avl_Tree 
{ 
... 
}; 

이유 중 하나는 나무의 취급 메모리의 처리를 분리하는 것입니다. 트리는 노드의 할당 또는 할당 해제에 신경 쓰지 않습니다. 노드를 키 값으로 간단하게 삽입, 삭제 또는 검색합니다. 기타 작업과 계속됩니다. 또 다른 이유는 노드가 가상 소멸자를 가졌는지 아닌지 응용 프로그램 상황에 따라 가능성을 허용하는 것입니다.

template <typename Key, class Compare = less<Key>> 
struct Avl_Tree : public Gen_Avl_Tree<AvlNode, Key, Compare> 
{ 
    using Base = Gen_Avl_Tree<AvlNode, Key, Compare>; 
    using Base::Base; 
}; 

    template <typename Key, class Compare = less<Key>> 
struct Avl_Tree_Vtl : public Gen_Avl_Tree<AvlNodeVtl, Key, Compare> 
{ 
    using Base = Gen_Avl_Tree<AvlNodeVtl, Key, Compare>; 
    using Base::Base; 
}; 

Avl_Tree이 "정상"노드와 Avl_Tree_Vtl 가상 소멸자와 노드를 사용을 사용하여 다음과 같이

그런 다음 나는 두 개의 클래스를 정의합니다. 두 유형 모두 중첩 유형 Node을 내 보냅니다. 예 : Avl_Tree::NodeAvl_Tree_Vtl::Node

두 클래스는 기능적으로 동일하다는 사실을 감상, 나는 다음과 같은 사항에 대해 이전 정의를 대체하는 것이 더 실용적 고려 :

template <typename Key, class Compare = less<Key>> 
using struct Avl_Tree = Gen_Avl_Tree<AvlNode, Key, Compare>; 

    template <typename Key, class Compare = less<Key>> 
using Avl_Tree_Vtl = Gen_Avl_Tree<AvlNodeVtl, Key, Compare>; 

그러나,이 마지막 방법은 컴파일러 오류가 발생합니다 (그 소리 컴파일러 3.6) 때 다음 함수의 인스턴스가 :

template < template <typename /* key */, class /* Compare */> class TreeType> 
void test(unsigned long n, gsl_rng * r) 
{ 
... 
    tuple<Stat, Stat, int, int> stats = sample_tree(tree, r, i, log(i)/log(2)); 
... 
} 
: 다른 함수에서

template <template <typename, class> class TreeType, 
     typename Key, 
     class Compare = Aleph::less<Key>> 
tuple<Stat, Stat, int, int> sample_tree(TreeType<Key, Compare> & tree, 
        gsl_rng * r, int n, int k) 
{ ... } 

test<Avl_Tree>(n, r); 

오류 발생 :로

라인 반대로

timeAllTree.C:190:6: error: no matching function for call to 'sample_tree' 
      sample_tree(tree, r, i, log(i)/log(2)); 
      ^~~~~~~~~~~ 
timeAllTree.C:344:4: note: in instantiation of function template specialization 
     'test<Avl_Tree>' requested here 
      test<Avl_Tree>(n, r); 
     ^
timeAllTree.C:56:29: note: candidate template ignored: could not match 'type-parameter-0-1' 
     against 'AvlNode' 
tuple<Stat, Stat, int, int> sample_tree(TreeType<Key, Compare> & tree, 
          ^

, Avl_TreeGen_Avl_Tree 컴파일로부터 유도로 정의하고 완벽하게 작동한다.

Gen_Avl_Tree에서 파생 된 Avl_Tree이 (가) Avl_Tree과 (과) 기능적으로 구별된다고 생각되는 이유가 있다면 제 질문입니다. 또는 컴파일러에 문제가 있습니까?

+1

별칭 템플릿은 템플릿 인수 공제 중 절대로 추론되지 않으므로 명시 적으로 'sample_tree'에 전달해야합니다. 'sample_tree'가 단순히'Tree' 형의 인수를 취할 수없는 어떤 이유가 있습니까? –

+0

문제를 재현하지 못했습니다. 나는 최소한의 예제를 만들려고했지만 괜찮습니다 : http://ideone.com/W0eRXJ –

+0

@VaughnCato 이상합니다. gcc와 clang 모두 실패하지만 훨씬 더 간단한 예제를 가지고 재현 할 수 있습니다 ... – Barry

답변

3

문제는 형식이 다르게 보입니다. 원래, 당신은 있었다 : KeyCompare : 그래서 Avl_Tree 2 종류의 템플릿이

template <typename Key, class Compare = less<Key>> 
struct Avl_Tree : public Gen_Avl_Tree<AvlNode, Key, Compare> 

입니다. 지금, 당신은이 : NodeType, KeyCompare :

여기
template <typename Key, class Compare = less<Key>> 
using struct Avl_Tree = Gen_Avl_Tree<AvlNode, Key, Compare>; 

, Avl_Tree는 유형에 대한 템플릿입니다 Gen_Avl_Tree 단지 별칭이다. 음, NodeType은 유형이 아니며 템플릿이지만 요점은 3 가지에 대한 템플릿입니다.이제

, 함수 :

template <template <typename, class> class TreeType, 
      typename Key, 
      class Compare = Aleph::less<Key>> 
tuple<Stat, Stat, int, int> sample_tree(TreeType<Key, Compare> & tree, 
       gsl_rng * r, int n, int k) 

는 두 종류의 소요 템플릿 템플릿을 기대하고있다. 별칭 -ed Avl_Tree과 일치 할 수 없으므로 정확한 컴파일러 오류가 발생합니다. 당신이 아마 대신하고 싶은 것은 : 함수의

template <typename Tree> 
tuple<Stat, Stat, int, int> sample_tree(Tree& tree, 
       gsl_rng * r, int n, int k) 
{ 
    // or equivalent... 
    using Key = typename Tree::Key; 
    using Compare = typename Tree::Compare; 
    // etc. 
} 

이 버전은 모두 파생 Avl_Tree 및 별칭 Avl_Tree을 위해 작동합니다.

+0

당신이 옳다고 생각하는 @ 배리. 'using'을 사용하면 그 물건이 별칭이되고 정말로 다른 클래스는 아닙니다. 당신의 도움을 주셔서 대단히 감사합니다 – lrleon