2015-02-05 3 views
2

템플릿 기능이 처음이므로이 오류를 파악할 수 없습니다. 당신이 도울 수 있기를 바랍니다.템플릿 함수를 올바르게 호출하는 방법은 무엇입니까?

#include <iostream> 
#include <vector> 

/* 
* Print to the screen the content of a vector 
* Define function template in the header 
*/ 
template <typename T> void print_vector(T& v) { 
    for(typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i) 
     std::cout << *i << ' '; 
} 

int main() { 
    std::vector<int> field; 
    field.resize(12, 1); 

    /* 
    for(std::vector<int>::const_iterator i = field.begin(); i != field.end(); ++i) 
     std::cout << *i << ' '; 
    */ 

    print_vector(field); 
} 

여기에 삽입 할 수없는 매우 긴 오류 메시지로 컴파일하지 못했습니다. 당신이

std::vector<int> field; 
... 
print_vector(field); 

를 호출 할 때

error: conversion from ‘std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}’ to non-scalar type ‘std::vector<std::vector<int>, std::allocator<std::vector<int> > >::const_iterator {aka __gnu_cxx::__normal_iterator<const std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >}’ requested 
utility.h:21:59: error: no match for ‘operator!=’ in ‘i != (& v)->std::vector<_Tp, _Alloc>::end<int, std::allocator<int> >()’ 
utility.h:21:59: note: candidates are: 
In file included from /usr/include/x86_64-linux-gnu/c++/4.7/./bits/c++allocator.h:34:0, 
       from /usr/include/c++/4.7/bits/allocator.h:48, 
       from /usr/include/c++/4.7/string:43, 
       from /usr/include/c++/4.7/bits/locale_classes.h:42, 
       from /usr/include/c++/4.7/bits/ios_base.h:43, 
       from /usr/include/c++/4.7/ios:43, 
       from /usr/include/c++/4.7/istream:40, 
       from /usr/include/c++/4.7/fstream:40, 
       from utility.h:4: 
/usr/include/c++/4.7/ext/new_allocator.h:134:5: note: template<class _Tp> bool __gnu_cxx::operator!=(const __gnu_cxx::new_allocator<_Tp>&, const __gnu_cxx::new_allocator<_Tp>&) 
/usr/include/c++/4.7/ext/new_allocator.h:134:5: note: template argument deduction/substitution failed: 
utility.h:21:59: note: ‘std::vector<std::vector<int>, std::allocator<std::vector<int> > >::const_iterator {aka __gnu_cxx::__normal_iterator<const std::vector<int>*, std::vector<std::vector<int>, std::allocator<std::vector<int> > > >}’ is not derived from ‘const __gnu_cxx::new_allocator<_Tp>’ 
+0

함수 시그니처에서,'T &'대신에'std :: vector '을 매개 변수 유형으로 사용해야합니다. – leemes

+1

C++에는 템플릿 기능이 없으며 "함수 템플릿"이 있습니다. 이것은 실제로 매우 적절한 차이입니다. C++에는 * 함수 용 템플릿 *이 있습니다. 즉, 컴파일러가 템플릿을 만드는 함수가 아니라 템플릿을 만듭니다. –

답변

4

는이 T1print_vector에, 즉, std::vector<int>field의 유형입니다. 따라서 typename std::vector<T>::const_iterator

for(typename std::vector<T>::const_iterator i = v.begin(); 

v.begin()는 (자체가 std::vector<int>::iterator를 되) 변환하지 않은하려면 std::vector<std::vector<int> >::const_iterator이다.

for(typename T::const_iterator i = v.begin(); 

을 대신 사용하십시오.

즉,이 경우 기능 템플릿 print_vector에서 작성된 함수에서. 함수에서

1

:

template <typename T> 
void print_vector(T& v) { 
    for(typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i) 
     std::cout << *i << ' '; 
} 

T, std::vector<int>로 추론된다 당신은 아닌 std::vector<std::vector<int>>::const_iterator (i의 종류)에 std::vector<int>::iterator (v.begin()의 결과를) 변환하려는 있도록 유효한 전환.

대신, 단지보다 전문적인 템플릿 기능을합니다

template <typename T> 
void print_vector(std::vector<T>& v) { 
    // as before 
} 
0

당신은 제대로 함수를 호출. 그런데 template-argument (컨테이너 유형)를 containers 요소 유형과 혼동했습니다.

어쨌든 const이 아닌 이유는 없습니다. 따라서

,이 대신과 같아야합니다

template <typename T> void print_vector(const T& v) { 
    for(typename T::const_iterator i = v.begin(); i != v.end(); ++i) 
     std::cout << *i << ' '; 
} 

또는 표준 라이브러리와 람다 사용 :

template <typename T> void print_vector(const T& v) { 
    using std::begin; // Using ADL for begin and end to support raw arrays 
    using std::end; 
    std::for_each(begin(v), end(v), [](auto&& x){std::cout<<*i<<' ';}); 
} 

또는 auto 및 범위 - 대한 - 루프 (내가 좋아하는) 사용하여 :

template <typename T> void print_vector(const T& v) { 
    for(auto&& i : v) 
     std::cout << *i << ' '; 
} 

또는 C++ 1z (2017 예상) :

void print_vector(const auto& v) { 
    for(auto&& i : v) 
     std::cout << *i << ' '; 
} 
+0

마지막위원회 회의에서 마지막 ('for (i : v)')이 거부되었습니다. –

+0

@ T.C .: 왜 그들은 그것을 거절 했습니까? 아십니까? – Deduplicator

+1

나는 그것이 선언처럼 보이지 않고 무언가를 (그리고 잠재적으로 그림자로) 선언 할 것이라는 우려 때문이라고 생각한다. 'int i = 0; 벡터 v {1}; for (i : v);','i'는 여전히 0입니다. –

0

어느 당신이 어떤 반복자에 합격하거나, 당신이 어떤 종류의 벡터에 대해 단지 작업에 대한 원한다면 void print_vector(std::vector<T>& v)에 적절하게 전문하려는 경우 단순히 T::const_iterator istd::vector<T>::const_iterator i를 교체합니다.

당신이 지금 가지고있는대로 치환을하면, 타입에서 벡터를 만드는 것에 벡터가 주어져서 벡터 벡터를 얻는 것을 볼 수 있습니다.

또한 GCC 4.8 및 4.9에는 개선 된 메시지가 있으며보다 정확한 오류 캐럿이 추가되었습니다. 이해할 수있는 컴파일러를 이동할 수 없다면 ideone.com과 같은 온라인 스 니펫과 같은 작은 스 니펫을 항상 제공 할 수 있습니다. 오류는 4.8에서 훨씬 더 간결하고 읽기 쉬울 것입니다.

아, C++ 11 기능에 액세스 할 수있는 경우 (4.7에서 무엇을 만들 었는지 기억하지 못합니다) 유형 선언을 자동으로 입력하고 유형 확인을 시작하는 대신 cbegin()과 같은 것을 사용할 수 있습니다 보통의 const_iterator 대신에 const_iterator를 선택한다. 템플릿에 대해 배우고 작업 환경에 제약이 없다면 C++ 11 및 더 최근의 GCC 로의 이동을 적극 권장합니다. 그러면 훨씬 쉽게 작업을 수행 할 수 있습니다.

관련 문제