2013-11-20 3 views
0

이 질문을 이해하기 위해 이전 질문에서 얻은 훌륭한 대답을 사용하려고했지만 왜이 코드가 컴파일되지 않는지 이해할 수 없습니다.템플릿 템플릿 매개 변수를 사용하는이 함수가 컴파일되지 않는 이유는 무엇입니까?

stack8test.cpp: In function int main(): 
stack8test.cpp:28: error: no matching function for call to Pout(Stack<int, std::vector>&) 
make: *** [stack8test.o] Error 1 

내가 도움을 주셔서 감사합니다 :

#include <iostream> 
#include <ostream> 
#include <string> 
#include <cstdlib> 
#include <vector> 
#include <memory> 

template <typename T, 
      template <typename ELEM, 
        typename = std::allocator<ELEM> > 
        class CONT = std::deque> 
class Stack { 

public: 
    typedef typename CONT<T>::size_type size_type; 

    private: 
    CONT<T> elems;   // elements 

    public: 
    void push(T const&); // push element 
    void pop();   // pop element 
    T top() const;   // return top element 
    bool empty() const { // return whether the stack is empty 
     return elems.empty(); 
    } 

     size_type size(); 
}; 

template <typename T, template <typename,typename> class CONT> 
void Stack<T,CONT>::push (T const& elem) 
{ 
    elems.push_back(elem); // append copy of passed elem 
} 

template<typename T, template <typename,typename> class CONT> 
void Stack<T,CONT>::pop() 
{ 
    if (elems.empty()) { 
     throw std::out_of_range("Stack<>::pop(): empty stack"); 
    } 
    elems.pop_back();   // remove last element 
} 

template <typename T, template <typename,typename> class CONT> 
T Stack<T,CONT>::top() const 
{ 
    if (elems.empty()) { 
     throw std::out_of_range("Stack<>::top(): empty stack"); 
    } 
    return elems.back();  // return copy of last element 
} 


template<typename T, 
template<typename, typename= std::allocator<T> > class CONT> 
typename Stack<T, CONT>::size_type Stack<T, CONT>::size() 
{ 
    return elems.size(); 
} 

template <typename T, 
      template <typename ELEM, typename = std::allocator<ELEM> > class CONT> 
static inline void Pout(const CONT<T>& container) 

{ 

    typedef typename CONT<T >::size_type size_type; 

    size_type idx = 0; 
    size_type sz = CONT<T>::size(); 

    CONT<T> temp = container; 
    std::cout << '['; 
    while (idx < sz) 
    { 
    std::cout << temp.top(); 
    temp.pop(); 
    idx++; 
    if (idx == sz) break; 
    std::cout << ", "; 
    } 
    std::cout << "]"; 
} 


int main() 
{ 
    try { 
    Stack<int, std::vector > vStack; 
    //... 
    vStack.push(42); 
    vStack.push(7); 

    Pout<Stack<int, std::vector > >(vStack); 
    } 
    catch (std::exception const& ex) { 
    std::cerr << "Exception: " << ex.what() << std::endl; 
    } 
} 

나는 ++ 4.3.4 g을 사용하여 컴파일러 오류가 발생합니다.

함수 호출을 Pout> (vStack)으로 주석 처리하고 vStack의 내용을 std :: cout으로 출력하도록 변경했습니다. 다음은 새로운 코드입니다. 그것은 컴파일하고 예상대로 작동합니다

#include <iostream> 
#include <ostream> 
#include <string> 
#include <cstdlib> 
#include <vector> 
#include <memory> 

#include <deque> 
#include <stdexcept> 

template <typename T, 
      template <typename ELEM, 
        typename = std::allocator<ELEM> > 
        class CONT = std::deque> 
class Stack { 

public: 
    typedef typename CONT<T>::size_type size_type; 
    typedef typename CONT<T>::value_type value_type; 

    private: 
    CONT<T> elems;   // elements 

    public: 
    void push(T const&); // push element 
    void pop();   // pop element 
    T top() const;   // return top element 
    bool empty() const { // return whether the stack is empty 
     return elems.empty(); 
    } 

    size_type size(); 
    void Pout(); 
}; 

template <typename T, template <typename,typename> class CONT> 
void Stack<T,CONT>::push (T const& elem) 
{ 
    elems.push_back(elem); // append copy of passed elem 
} 

template<typename T, template <typename,typename> class CONT> 
void Stack<T,CONT>::pop() 
{ 
    if (elems.empty()) { 
     throw std::out_of_range("Stack<>::pop(): empty stack"); 
    } 
    elems.pop_back();   // remove last element 
} 

template <typename T, template <typename,typename> class CONT> 
T Stack<T,CONT>::top() const 
{ 
    if (elems.empty()) { 
     throw std::out_of_range("Stack<>::top(): empty stack"); 
    } 
    return elems.back();  // return copy of last element 
} 


template<typename T, 
template<typename, typename= std::allocator<T> > class CONT> 
typename Stack<T, CONT>::size_type Stack<T, CONT>::size() 
{ 
    return elems.size(); 
} 


template <typename T, 
template<typename, typename = std::allocator<T> > class CONT> 
void Stack<T, CONT>::Pout() 
{ 

    size_type idx = 0; 
    size_type sz = size(); 

    CONT<T> temp(elems); // make a temp copy of the underlying container and print the temp, since printing is destructive. Note that the underlying CONT must already support copy constructor. 

    std::cout << std::endl << '['; 
    while (idx < sz) 
    { 
    std::cout << temp.back(); 
    temp.pop_back(); 
    idx++; 
    if (idx == sz) break; 
    std::cout << ", "; 
    } 
    std::cout << "]" << std::endl;; 

} 
template <typename T, 
      template <typename ELEM, typename = std::allocator<ELEM> > class CONT> 
void Pout(const CONT<T>& container) 

{ 

    typedef typename CONT<T >::size_type size_type; 

    size_type idx = 0; 
    size_type sz = CONT<T>::size(); 

    CONT<T> temp = container; 
    std::cout << '['; 
    while (idx < sz) 
    { 
    std::cout << temp.top(); 
    temp.pop(); 
    idx++; 
    if (idx == sz) break; 
    std::cout << ", "; 
    } 
    std::cout << "]"; 
} 


int main() 
{ 
    try { 
    Stack<int, std::vector > vStack; 
    //... 
    vStack.push(42); 
    vStack.push(7); 

// Pout<Stack<int, std::vector > >(vStack); 
    vStack.Pout(); 
    std::cout << "vStack = [" << vStack.top(); vStack.pop(); 
    std::cout << ", " << vStack.top() << "]" << std::endl; vStack.pop(); 
    } 
    catch (std::exception const& ex) { 
    std::cerr << "Exception: " << ex.what() << std::endl; 
    } 
} 

컴파일러의 출력은 다음과 같습니다

g++ -O2 -g -Wall -c -o stack8test stack8test.cpp 

프로그램을 실행, 내가 가지고 :

./stack8test 
vStack = [7, 42] 

내 진짜 문제는 대한 올바른 구문을 찾는 것입니다 함수 템플릿 Pout 내 클래스 템플릿 Stack의 내용을 출력합니다. 명확히하기 위해, 클래스 템플릿 Stack을 T 타입의 요소 컨테이너로 구현하는 것입니다. std :: vector 또는 std :: deque 형식의 std 컨테이너 또는 Std :: list의 관점에서 Stack을 구현하고 싶습니다. .

나는대로 메기라고 :

Pout<int, Stack<int, std::vector>>(vStack); 

그러나 컴파일러는 여전히 말한다 :

stack8test.cpp: In function int main(): 
stack8test.cpp:137: error: no matching function for call to Pout(Stack<int, std::vector>&) 
make: *** [stack8test.o] Error 1 

UPDATE : 글로벌의 내 원래 원래 문제에 대한 주위의 작품으로 (즉, 비회원) 함수는 내 스택의 내용을 std :: cout으로 출력하기 위해 Pout()을 멤버 함수로 정의했다. 그것은 컴파일하고 예상대로 작동합니다. 전역 함수에 대한 올바른 구문을 찾는 것은 여전히 ​​어려운 과제입니다.

+0

'std :: deque'를 사용하면 헤더도 포함해야합니다 (). – dyp

+0

더 일찍 언급하지 않으셔서 죄송합니다. 나는 아프다. – user2975538

+0

죄송합니다. 나는 아프다. 내 디자인을 잘 모르겠다. Stack은 STL 컨테이너 중 하나 (vector 또는 deque)로 구현할 수있는 클래스 템플릿 컨테이너이다. 합리적인 디자인이라고 생각합니다. @Mikhail – user2975538

답변

2

너는 너무 복잡해. 당신은 컴파일러가 단순히이 그것이 STL에서 수행하는 방법이다

template <class CONT> 
static inline void Pout(const CONT& container) 

쓰기 가능한 대신 쓰기

template <typename T, 
     template <typename ELEM, typename = std::allocator<ELEM> > class CONT> 
static inline void Pout(const CONT<T>& container) 

의 당신을 위해 많은 정보를 추론 할 수 있도록해야한다. 다시, 컨테이너의 기본 유형에 액세스해야하는 경우 STL 접근 방식을 사용하고 클래스에 value_type 타입 정의를 추가

class Stack { 
public: 
    ... 
    typedef T value_type; 
    ... 
} 

당신은 다음 CONT::value_type으로 기능에 액세스 할 수 있습니다. 그러나 Pout 함수에서이 정보를 사용하지 않아도됩니다.

일부 다른 오류 : const

  • 마크 size 기능은 당신이 당신이 무슨 일을하는지 알고 100 % 확신하지 않는 한 functionы에 대한
  • static inline 지정자를 사용하지 마십시오해야한다. 아마도 당신은 그렇지 않습니다.

코드는 이러한 오류를 수정 한 후에 컴파일되지만 전체 디자인은 매우 열악합니다.

+0

내 스택은 STL 벡터 또는 deque 컨테이너의 관점에서 구현되는 클래스 템플릿입니다. 스택 요소 유형 T와 stl 컨테이너 유형 CONT는 모두 매개 변수입니다. 따라서 매개 변수 CONT는 템플릿 템플릿 매개 변수 여야합니다. Pout은 my Stack > 요소를 std :: cout에 인쇄하는 템플릿 함수입니다. 이 개념에 문제가 있습니까? – user2975538

+0

이 개념으로 해결하려는 작업에 따라 다릅니다. C++에서 템플릿 프로그래밍에 대한 첫 번째 규칙은 필요하다고 확신하지 않는 한 복잡하지 않도록하는 것입니다. – Mikhail

관련 문제